├── .circleci └── config.yml ├── .dockerignore ├── .github └── workflows │ ├── build.yml │ └── reviewdog.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── README.md ├── renovate.json └── src ├── main.rs ├── ump_stream.rs └── utils.rs /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | jobs: 4 | arm64: 5 | machine: 6 | image: ubuntu-2004:current 7 | resource_class: arm.medium 8 | steps: 9 | - checkout 10 | - run: 11 | command: | 12 | export DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=plain 13 | docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD 14 | docker build -t 1337kavin/piped-proxy:latest-arm64 . 15 | docker push 1337kavin/piped-proxy:latest-arm64 16 | amd64: 17 | machine: 18 | image: ubuntu-2004:current 19 | resource_class: medium 20 | steps: 21 | - checkout 22 | - run: 23 | command: | 24 | export DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=plain 25 | docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD 26 | docker build -t 1337kavin/piped-proxy:latest-amd64 . 27 | docker push 1337kavin/piped-proxy:latest-amd64 28 | push: 29 | machine: 30 | image: ubuntu-2004:current 31 | resource_class: medium 32 | steps: 33 | - run: 34 | command: | 35 | docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD 36 | docker manifest create 1337kavin/piped-proxy:latest 1337kavin/piped-proxy:latest-arm64 1337kavin/piped-proxy:latest-amd64 37 | docker manifest push 1337kavin/piped-proxy:latest 38 | 39 | workflows: 40 | build-docker: 41 | jobs: 42 | - arm64: 43 | filters: 44 | branches: 45 | only: main 46 | - amd64: 47 | filters: 48 | branches: 49 | only: main 50 | - push: 51 | filters: 52 | branches: 53 | only: main 54 | requires: 55 | - arm64 56 | - amd64 57 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.md 3 | target/ 4 | LICENSE 5 | *.json 6 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build using Cargo 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - "**.md" 7 | branches: 8 | - main 9 | pull_request: 10 | paths-ignore: 11 | - "**.md" 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: Swatinem/rust-cache@v2 19 | - uses: rui314/setup-mold@v1 20 | - name: Set up NASM 21 | uses: ilammy/setup-nasm@v1.5.2 22 | - name: Build 23 | run: RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-unknown-linux-gnu 24 | - run: mv target/x86_64-unknown-linux-gnu/release/piped-proxy piped-proxy 25 | - name: Upload artifact 26 | uses: actions/upload-artifact@v4 27 | with: 28 | name: piped-proxy 29 | path: piped-proxy 30 | -------------------------------------------------------------------------------- /.github/workflows/reviewdog.yml: -------------------------------------------------------------------------------- 1 | name: reviewdog / clippy 2 | on: pull_request 3 | jobs: 4 | clippy: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v4 8 | - name: Install clippy 9 | uses: dtolnay/rust-toolchain@stable 10 | with: 11 | components: clippy 12 | - uses: Swatinem/rust-cache@v2 13 | 14 | - uses: sksat/action-clippy@main 15 | with: 16 | reporter: github-pr-review 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | /target 3 | *.sock 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "actix-codec" 7 | version = "0.5.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" 10 | dependencies = [ 11 | "bitflags", 12 | "bytes", 13 | "futures-core", 14 | "futures-sink", 15 | "memchr", 16 | "pin-project-lite", 17 | "tokio", 18 | "tokio-util", 19 | "tracing", 20 | ] 21 | 22 | [[package]] 23 | name = "actix-http" 24 | version = "3.11.0" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2" 27 | dependencies = [ 28 | "actix-codec", 29 | "actix-rt", 30 | "actix-service", 31 | "actix-utils", 32 | "base64", 33 | "bitflags", 34 | "brotli", 35 | "bytes", 36 | "bytestring", 37 | "derive_more", 38 | "encoding_rs", 39 | "flate2", 40 | "foldhash", 41 | "futures-core", 42 | "h2", 43 | "http 0.2.12", 44 | "httparse", 45 | "httpdate", 46 | "itoa", 47 | "language-tags", 48 | "local-channel", 49 | "mime", 50 | "percent-encoding", 51 | "pin-project-lite", 52 | "rand 0.9.1", 53 | "sha1", 54 | "smallvec", 55 | "tokio", 56 | "tokio-util", 57 | "tracing", 58 | "zstd", 59 | ] 60 | 61 | [[package]] 62 | name = "actix-macros" 63 | version = "0.2.4" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" 66 | dependencies = [ 67 | "quote", 68 | "syn", 69 | ] 70 | 71 | [[package]] 72 | name = "actix-router" 73 | version = "0.5.3" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" 76 | dependencies = [ 77 | "bytestring", 78 | "cfg-if", 79 | "http 0.2.12", 80 | "regex", 81 | "regex-lite", 82 | "serde", 83 | "tracing", 84 | ] 85 | 86 | [[package]] 87 | name = "actix-rt" 88 | version = "2.10.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" 91 | dependencies = [ 92 | "futures-core", 93 | "tokio", 94 | ] 95 | 96 | [[package]] 97 | name = "actix-server" 98 | version = "2.6.0" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" 101 | dependencies = [ 102 | "actix-rt", 103 | "actix-service", 104 | "actix-utils", 105 | "futures-core", 106 | "futures-util", 107 | "mio", 108 | "socket2", 109 | "tokio", 110 | "tracing", 111 | ] 112 | 113 | [[package]] 114 | name = "actix-service" 115 | version = "2.0.3" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" 118 | dependencies = [ 119 | "futures-core", 120 | "pin-project-lite", 121 | ] 122 | 123 | [[package]] 124 | name = "actix-utils" 125 | version = "3.0.1" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" 128 | dependencies = [ 129 | "local-waker", 130 | "pin-project-lite", 131 | ] 132 | 133 | [[package]] 134 | name = "actix-web" 135 | version = "4.11.0" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea" 138 | dependencies = [ 139 | "actix-codec", 140 | "actix-http", 141 | "actix-macros", 142 | "actix-router", 143 | "actix-rt", 144 | "actix-server", 145 | "actix-service", 146 | "actix-utils", 147 | "actix-web-codegen", 148 | "bytes", 149 | "bytestring", 150 | "cfg-if", 151 | "cookie", 152 | "derive_more", 153 | "encoding_rs", 154 | "foldhash", 155 | "futures-core", 156 | "futures-util", 157 | "impl-more", 158 | "itoa", 159 | "language-tags", 160 | "log", 161 | "mime", 162 | "once_cell", 163 | "pin-project-lite", 164 | "regex", 165 | "regex-lite", 166 | "serde", 167 | "serde_json", 168 | "serde_urlencoded", 169 | "smallvec", 170 | "socket2", 171 | "time", 172 | "tracing", 173 | "url", 174 | ] 175 | 176 | [[package]] 177 | name = "actix-web-codegen" 178 | version = "4.3.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" 181 | dependencies = [ 182 | "actix-router", 183 | "proc-macro2", 184 | "quote", 185 | "syn", 186 | ] 187 | 188 | [[package]] 189 | name = "addr2line" 190 | version = "0.24.2" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 193 | dependencies = [ 194 | "gimli", 195 | ] 196 | 197 | [[package]] 198 | name = "adler2" 199 | version = "2.0.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 202 | 203 | [[package]] 204 | name = "aho-corasick" 205 | version = "1.1.3" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 208 | dependencies = [ 209 | "memchr", 210 | ] 211 | 212 | [[package]] 213 | name = "aligned-vec" 214 | version = "0.5.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" 217 | 218 | [[package]] 219 | name = "alloc-no-stdlib" 220 | version = "2.0.4" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 223 | 224 | [[package]] 225 | name = "alloc-stdlib" 226 | version = "0.2.2" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 229 | dependencies = [ 230 | "alloc-no-stdlib", 231 | ] 232 | 233 | [[package]] 234 | name = "anyhow" 235 | version = "1.0.98" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 238 | 239 | [[package]] 240 | name = "arbitrary" 241 | version = "1.4.1" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" 244 | 245 | [[package]] 246 | name = "arg_enum_proc_macro" 247 | version = "0.3.4" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" 250 | dependencies = [ 251 | "proc-macro2", 252 | "quote", 253 | "syn", 254 | ] 255 | 256 | [[package]] 257 | name = "arrayref" 258 | version = "0.3.9" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" 261 | 262 | [[package]] 263 | name = "arrayvec" 264 | version = "0.7.6" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 267 | 268 | [[package]] 269 | name = "async-compression" 270 | version = "0.4.23" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "b37fc50485c4f3f736a4fb14199f6d5f5ba008d7f28fe710306c92780f004c07" 273 | dependencies = [ 274 | "brotli", 275 | "flate2", 276 | "futures-core", 277 | "memchr", 278 | "pin-project-lite", 279 | "tokio", 280 | ] 281 | 282 | [[package]] 283 | name = "autocfg" 284 | version = "1.4.0" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 287 | 288 | [[package]] 289 | name = "av1-grain" 290 | version = "0.2.4" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" 293 | dependencies = [ 294 | "anyhow", 295 | "arrayvec", 296 | "log", 297 | "nom", 298 | "num-rational", 299 | "v_frame", 300 | ] 301 | 302 | [[package]] 303 | name = "avif-serialize" 304 | version = "0.8.3" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" 307 | dependencies = [ 308 | "arrayvec", 309 | ] 310 | 311 | [[package]] 312 | name = "backtrace" 313 | version = "0.3.75" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 316 | dependencies = [ 317 | "addr2line", 318 | "cfg-if", 319 | "libc", 320 | "miniz_oxide", 321 | "object", 322 | "rustc-demangle", 323 | "windows-targets", 324 | ] 325 | 326 | [[package]] 327 | name = "base64" 328 | version = "0.22.1" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 331 | 332 | [[package]] 333 | name = "bitflags" 334 | version = "2.9.1" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 337 | 338 | [[package]] 339 | name = "bitstream-io" 340 | version = "2.6.0" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" 343 | 344 | [[package]] 345 | name = "blake3" 346 | version = "1.8.2" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" 349 | dependencies = [ 350 | "arrayref", 351 | "arrayvec", 352 | "cc", 353 | "cfg-if", 354 | "constant_time_eq", 355 | ] 356 | 357 | [[package]] 358 | name = "block-buffer" 359 | version = "0.10.4" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 362 | dependencies = [ 363 | "generic-array", 364 | ] 365 | 366 | [[package]] 367 | name = "brotli" 368 | version = "8.0.1" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" 371 | dependencies = [ 372 | "alloc-no-stdlib", 373 | "alloc-stdlib", 374 | "brotli-decompressor", 375 | ] 376 | 377 | [[package]] 378 | name = "brotli-decompressor" 379 | version = "5.0.0" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" 382 | dependencies = [ 383 | "alloc-no-stdlib", 384 | "alloc-stdlib", 385 | ] 386 | 387 | [[package]] 388 | name = "built" 389 | version = "0.7.7" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" 392 | 393 | [[package]] 394 | name = "bumpalo" 395 | version = "3.17.0" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 398 | 399 | [[package]] 400 | name = "bytemuck" 401 | version = "1.23.0" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" 404 | 405 | [[package]] 406 | name = "byteorder-lite" 407 | version = "0.1.0" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" 410 | 411 | [[package]] 412 | name = "bytes" 413 | version = "1.10.1" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 416 | 417 | [[package]] 418 | name = "bytestring" 419 | version = "1.4.0" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" 422 | dependencies = [ 423 | "bytes", 424 | ] 425 | 426 | [[package]] 427 | name = "cc" 428 | version = "1.2.25" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" 431 | dependencies = [ 432 | "jobserver", 433 | "libc", 434 | "shlex", 435 | ] 436 | 437 | [[package]] 438 | name = "cfg-expr" 439 | version = "0.15.8" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" 442 | dependencies = [ 443 | "smallvec", 444 | "target-lexicon", 445 | ] 446 | 447 | [[package]] 448 | name = "cfg-if" 449 | version = "1.0.0" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 452 | 453 | [[package]] 454 | name = "cfg_aliases" 455 | version = "0.2.1" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 458 | 459 | [[package]] 460 | name = "constant_time_eq" 461 | version = "0.3.1" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" 464 | 465 | [[package]] 466 | name = "cookie" 467 | version = "0.16.2" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" 470 | dependencies = [ 471 | "percent-encoding", 472 | "time", 473 | "version_check", 474 | ] 475 | 476 | [[package]] 477 | name = "core-foundation" 478 | version = "0.9.4" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 481 | dependencies = [ 482 | "core-foundation-sys", 483 | "libc", 484 | ] 485 | 486 | [[package]] 487 | name = "core-foundation-sys" 488 | version = "0.8.7" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 491 | 492 | [[package]] 493 | name = "cpufeatures" 494 | version = "0.2.17" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 497 | dependencies = [ 498 | "libc", 499 | ] 500 | 501 | [[package]] 502 | name = "crc32fast" 503 | version = "1.4.2" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 506 | dependencies = [ 507 | "cfg-if", 508 | ] 509 | 510 | [[package]] 511 | name = "crossbeam-deque" 512 | version = "0.8.6" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 515 | dependencies = [ 516 | "crossbeam-epoch", 517 | "crossbeam-utils", 518 | ] 519 | 520 | [[package]] 521 | name = "crossbeam-epoch" 522 | version = "0.9.18" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 525 | dependencies = [ 526 | "crossbeam-utils", 527 | ] 528 | 529 | [[package]] 530 | name = "crossbeam-utils" 531 | version = "0.8.21" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 534 | 535 | [[package]] 536 | name = "crypto-common" 537 | version = "0.1.6" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 540 | dependencies = [ 541 | "generic-array", 542 | "typenum", 543 | ] 544 | 545 | [[package]] 546 | name = "deranged" 547 | version = "0.4.0" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" 550 | dependencies = [ 551 | "powerfmt", 552 | ] 553 | 554 | [[package]] 555 | name = "derive_more" 556 | version = "2.0.1" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" 559 | dependencies = [ 560 | "derive_more-impl", 561 | ] 562 | 563 | [[package]] 564 | name = "derive_more-impl" 565 | version = "2.0.1" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" 568 | dependencies = [ 569 | "proc-macro2", 570 | "quote", 571 | "syn", 572 | "unicode-xid", 573 | ] 574 | 575 | [[package]] 576 | name = "digest" 577 | version = "0.10.7" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 580 | dependencies = [ 581 | "block-buffer", 582 | "crypto-common", 583 | ] 584 | 585 | [[package]] 586 | name = "displaydoc" 587 | version = "0.2.5" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 590 | dependencies = [ 591 | "proc-macro2", 592 | "quote", 593 | "syn", 594 | ] 595 | 596 | [[package]] 597 | name = "either" 598 | version = "1.15.0" 599 | source = "registry+https://github.com/rust-lang/crates.io-index" 600 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 601 | 602 | [[package]] 603 | name = "encoding_rs" 604 | version = "0.8.35" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 607 | dependencies = [ 608 | "cfg-if", 609 | ] 610 | 611 | [[package]] 612 | name = "equivalent" 613 | version = "1.0.2" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 616 | 617 | [[package]] 618 | name = "errno" 619 | version = "0.3.12" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" 622 | dependencies = [ 623 | "libc", 624 | "windows-sys 0.59.0", 625 | ] 626 | 627 | [[package]] 628 | name = "fastrand" 629 | version = "2.3.0" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 632 | 633 | [[package]] 634 | name = "flate2" 635 | version = "1.1.1" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" 638 | dependencies = [ 639 | "crc32fast", 640 | "miniz_oxide", 641 | ] 642 | 643 | [[package]] 644 | name = "fnv" 645 | version = "1.0.7" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 648 | 649 | [[package]] 650 | name = "foldhash" 651 | version = "0.1.5" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 654 | 655 | [[package]] 656 | name = "foreign-types" 657 | version = "0.3.2" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 660 | dependencies = [ 661 | "foreign-types-shared", 662 | ] 663 | 664 | [[package]] 665 | name = "foreign-types-shared" 666 | version = "0.1.1" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 669 | 670 | [[package]] 671 | name = "form_urlencoded" 672 | version = "1.2.1" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 675 | dependencies = [ 676 | "percent-encoding", 677 | ] 678 | 679 | [[package]] 680 | name = "futures-channel" 681 | version = "0.3.31" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 684 | dependencies = [ 685 | "futures-core", 686 | ] 687 | 688 | [[package]] 689 | name = "futures-core" 690 | version = "0.3.31" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 693 | 694 | [[package]] 695 | name = "futures-io" 696 | version = "0.3.31" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 699 | 700 | [[package]] 701 | name = "futures-macro" 702 | version = "0.3.31" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 705 | dependencies = [ 706 | "proc-macro2", 707 | "quote", 708 | "syn", 709 | ] 710 | 711 | [[package]] 712 | name = "futures-sink" 713 | version = "0.3.31" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 716 | 717 | [[package]] 718 | name = "futures-task" 719 | version = "0.3.31" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 722 | 723 | [[package]] 724 | name = "futures-util" 725 | version = "0.3.31" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 728 | dependencies = [ 729 | "futures-core", 730 | "futures-io", 731 | "futures-macro", 732 | "futures-sink", 733 | "futures-task", 734 | "memchr", 735 | "pin-project-lite", 736 | "pin-utils", 737 | "slab", 738 | ] 739 | 740 | [[package]] 741 | name = "generic-array" 742 | version = "0.14.7" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 745 | dependencies = [ 746 | "typenum", 747 | "version_check", 748 | ] 749 | 750 | [[package]] 751 | name = "getrandom" 752 | version = "0.2.16" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 755 | dependencies = [ 756 | "cfg-if", 757 | "js-sys", 758 | "libc", 759 | "wasi 0.11.0+wasi-snapshot-preview1", 760 | "wasm-bindgen", 761 | ] 762 | 763 | [[package]] 764 | name = "getrandom" 765 | version = "0.3.3" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 768 | dependencies = [ 769 | "cfg-if", 770 | "js-sys", 771 | "libc", 772 | "r-efi", 773 | "wasi 0.14.2+wasi-0.2.4", 774 | "wasm-bindgen", 775 | ] 776 | 777 | [[package]] 778 | name = "gimli" 779 | version = "0.31.1" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 782 | 783 | [[package]] 784 | name = "glob" 785 | version = "0.3.2" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" 788 | 789 | [[package]] 790 | name = "h2" 791 | version = "0.3.26" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 794 | dependencies = [ 795 | "bytes", 796 | "fnv", 797 | "futures-core", 798 | "futures-sink", 799 | "futures-util", 800 | "http 0.2.12", 801 | "indexmap", 802 | "slab", 803 | "tokio", 804 | "tokio-util", 805 | "tracing", 806 | ] 807 | 808 | [[package]] 809 | name = "hashbrown" 810 | version = "0.15.3" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" 813 | 814 | [[package]] 815 | name = "heck" 816 | version = "0.5.0" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 819 | 820 | [[package]] 821 | name = "http" 822 | version = "0.2.12" 823 | source = "registry+https://github.com/rust-lang/crates.io-index" 824 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 825 | dependencies = [ 826 | "bytes", 827 | "fnv", 828 | "itoa", 829 | ] 830 | 831 | [[package]] 832 | name = "http" 833 | version = "1.3.1" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 836 | dependencies = [ 837 | "bytes", 838 | "fnv", 839 | "itoa", 840 | ] 841 | 842 | [[package]] 843 | name = "http-body" 844 | version = "1.0.1" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 847 | dependencies = [ 848 | "bytes", 849 | "http 1.3.1", 850 | ] 851 | 852 | [[package]] 853 | name = "http-body-util" 854 | version = "0.1.3" 855 | source = "registry+https://github.com/rust-lang/crates.io-index" 856 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 857 | dependencies = [ 858 | "bytes", 859 | "futures-core", 860 | "http 1.3.1", 861 | "http-body", 862 | "pin-project-lite", 863 | ] 864 | 865 | [[package]] 866 | name = "httparse" 867 | version = "1.10.1" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 870 | 871 | [[package]] 872 | name = "httpdate" 873 | version = "1.0.3" 874 | source = "registry+https://github.com/rust-lang/crates.io-index" 875 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 876 | 877 | [[package]] 878 | name = "hyper" 879 | version = "1.6.0" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 882 | dependencies = [ 883 | "bytes", 884 | "futures-channel", 885 | "futures-util", 886 | "http 1.3.1", 887 | "http-body", 888 | "httparse", 889 | "itoa", 890 | "pin-project-lite", 891 | "smallvec", 892 | "tokio", 893 | "want", 894 | ] 895 | 896 | [[package]] 897 | name = "hyper-rustls" 898 | version = "0.27.6" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d" 901 | dependencies = [ 902 | "http 1.3.1", 903 | "hyper", 904 | "hyper-util", 905 | "rustls", 906 | "rustls-pki-types", 907 | "tokio", 908 | "tokio-rustls", 909 | "tower-service", 910 | "webpki-roots", 911 | ] 912 | 913 | [[package]] 914 | name = "hyper-tls" 915 | version = "0.6.0" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 918 | dependencies = [ 919 | "bytes", 920 | "http-body-util", 921 | "hyper", 922 | "hyper-util", 923 | "native-tls", 924 | "tokio", 925 | "tokio-native-tls", 926 | "tower-service", 927 | ] 928 | 929 | [[package]] 930 | name = "hyper-util" 931 | version = "0.1.13" 932 | source = "registry+https://github.com/rust-lang/crates.io-index" 933 | checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" 934 | dependencies = [ 935 | "base64", 936 | "bytes", 937 | "futures-channel", 938 | "futures-core", 939 | "futures-util", 940 | "http 1.3.1", 941 | "http-body", 942 | "hyper", 943 | "ipnet", 944 | "libc", 945 | "percent-encoding", 946 | "pin-project-lite", 947 | "socket2", 948 | "tokio", 949 | "tower-service", 950 | "tracing", 951 | ] 952 | 953 | [[package]] 954 | name = "icu_collections" 955 | version = "2.0.0" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 958 | dependencies = [ 959 | "displaydoc", 960 | "potential_utf", 961 | "yoke", 962 | "zerofrom", 963 | "zerovec", 964 | ] 965 | 966 | [[package]] 967 | name = "icu_locale_core" 968 | version = "2.0.0" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 971 | dependencies = [ 972 | "displaydoc", 973 | "litemap", 974 | "tinystr", 975 | "writeable", 976 | "zerovec", 977 | ] 978 | 979 | [[package]] 980 | name = "icu_normalizer" 981 | version = "2.0.0" 982 | source = "registry+https://github.com/rust-lang/crates.io-index" 983 | checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 984 | dependencies = [ 985 | "displaydoc", 986 | "icu_collections", 987 | "icu_normalizer_data", 988 | "icu_properties", 989 | "icu_provider", 990 | "smallvec", 991 | "zerovec", 992 | ] 993 | 994 | [[package]] 995 | name = "icu_normalizer_data" 996 | version = "2.0.0" 997 | source = "registry+https://github.com/rust-lang/crates.io-index" 998 | checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 999 | 1000 | [[package]] 1001 | name = "icu_properties" 1002 | version = "2.0.1" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 1005 | dependencies = [ 1006 | "displaydoc", 1007 | "icu_collections", 1008 | "icu_locale_core", 1009 | "icu_properties_data", 1010 | "icu_provider", 1011 | "potential_utf", 1012 | "zerotrie", 1013 | "zerovec", 1014 | ] 1015 | 1016 | [[package]] 1017 | name = "icu_properties_data" 1018 | version = "2.0.1" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 1021 | 1022 | [[package]] 1023 | name = "icu_provider" 1024 | version = "2.0.0" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 1027 | dependencies = [ 1028 | "displaydoc", 1029 | "icu_locale_core", 1030 | "stable_deref_trait", 1031 | "tinystr", 1032 | "writeable", 1033 | "yoke", 1034 | "zerofrom", 1035 | "zerotrie", 1036 | "zerovec", 1037 | ] 1038 | 1039 | [[package]] 1040 | name = "idna" 1041 | version = "1.0.3" 1042 | source = "registry+https://github.com/rust-lang/crates.io-index" 1043 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1044 | dependencies = [ 1045 | "idna_adapter", 1046 | "smallvec", 1047 | "utf8_iter", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "idna_adapter" 1052 | version = "1.2.1" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 1055 | dependencies = [ 1056 | "icu_normalizer", 1057 | "icu_properties", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "image" 1062 | version = "0.25.6" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" 1065 | dependencies = [ 1066 | "bytemuck", 1067 | "byteorder-lite", 1068 | "image-webp", 1069 | "num-traits", 1070 | "ravif", 1071 | "rayon", 1072 | "zune-core", 1073 | "zune-jpeg", 1074 | ] 1075 | 1076 | [[package]] 1077 | name = "image-webp" 1078 | version = "0.2.1" 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" 1080 | checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" 1081 | dependencies = [ 1082 | "byteorder-lite", 1083 | "quick-error", 1084 | ] 1085 | 1086 | [[package]] 1087 | name = "imgref" 1088 | version = "1.11.0" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" 1091 | 1092 | [[package]] 1093 | name = "impl-more" 1094 | version = "0.1.9" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" 1097 | 1098 | [[package]] 1099 | name = "indexmap" 1100 | version = "2.9.0" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 1103 | dependencies = [ 1104 | "equivalent", 1105 | "hashbrown", 1106 | ] 1107 | 1108 | [[package]] 1109 | name = "interpolate_name" 1110 | version = "0.2.4" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" 1113 | dependencies = [ 1114 | "proc-macro2", 1115 | "quote", 1116 | "syn", 1117 | ] 1118 | 1119 | [[package]] 1120 | name = "ipnet" 1121 | version = "2.11.0" 1122 | source = "registry+https://github.com/rust-lang/crates.io-index" 1123 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1124 | 1125 | [[package]] 1126 | name = "iri-string" 1127 | version = "0.7.8" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" 1130 | dependencies = [ 1131 | "memchr", 1132 | "serde", 1133 | ] 1134 | 1135 | [[package]] 1136 | name = "itertools" 1137 | version = "0.12.1" 1138 | source = "registry+https://github.com/rust-lang/crates.io-index" 1139 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 1140 | dependencies = [ 1141 | "either", 1142 | ] 1143 | 1144 | [[package]] 1145 | name = "itoa" 1146 | version = "1.0.15" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 1149 | 1150 | [[package]] 1151 | name = "jobserver" 1152 | version = "0.1.33" 1153 | source = "registry+https://github.com/rust-lang/crates.io-index" 1154 | checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" 1155 | dependencies = [ 1156 | "getrandom 0.3.3", 1157 | "libc", 1158 | ] 1159 | 1160 | [[package]] 1161 | name = "js-sys" 1162 | version = "0.3.77" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 1165 | dependencies = [ 1166 | "once_cell", 1167 | "wasm-bindgen", 1168 | ] 1169 | 1170 | [[package]] 1171 | name = "language-tags" 1172 | version = "0.3.2" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 1175 | 1176 | [[package]] 1177 | name = "libc" 1178 | version = "0.2.172" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 1181 | 1182 | [[package]] 1183 | name = "libfuzzer-sys" 1184 | version = "0.4.9" 1185 | source = "registry+https://github.com/rust-lang/crates.io-index" 1186 | checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" 1187 | dependencies = [ 1188 | "arbitrary", 1189 | "cc", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "libmimalloc-sys" 1194 | version = "0.1.42" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "ec9d6fac27761dabcd4ee73571cdb06b7022dc99089acbe5435691edffaac0f4" 1197 | dependencies = [ 1198 | "cc", 1199 | "libc", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "libwebp-sys" 1204 | version = "0.12.1" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "da0861afa659bb092b2fbeb87a618b227daf7c3b9507274b05443c87a3e38790" 1207 | dependencies = [ 1208 | "cc", 1209 | "glob", 1210 | "pkg-config", 1211 | ] 1212 | 1213 | [[package]] 1214 | name = "linux-raw-sys" 1215 | version = "0.9.4" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" 1218 | 1219 | [[package]] 1220 | name = "listenfd" 1221 | version = "1.0.2" 1222 | source = "registry+https://github.com/rust-lang/crates.io-index" 1223 | checksum = "b87bc54a4629b4294d0b3ef041b64c40c611097a677d9dc07b2c67739fe39dba" 1224 | dependencies = [ 1225 | "libc", 1226 | "uuid", 1227 | "winapi", 1228 | ] 1229 | 1230 | [[package]] 1231 | name = "litemap" 1232 | version = "0.8.0" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 1235 | 1236 | [[package]] 1237 | name = "local-channel" 1238 | version = "0.1.5" 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" 1240 | checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" 1241 | dependencies = [ 1242 | "futures-core", 1243 | "futures-sink", 1244 | "local-waker", 1245 | ] 1246 | 1247 | [[package]] 1248 | name = "local-waker" 1249 | version = "0.1.4" 1250 | source = "registry+https://github.com/rust-lang/crates.io-index" 1251 | checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" 1252 | 1253 | [[package]] 1254 | name = "lock_api" 1255 | version = "0.4.13" 1256 | source = "registry+https://github.com/rust-lang/crates.io-index" 1257 | checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" 1258 | dependencies = [ 1259 | "autocfg", 1260 | "scopeguard", 1261 | ] 1262 | 1263 | [[package]] 1264 | name = "log" 1265 | version = "0.4.27" 1266 | source = "registry+https://github.com/rust-lang/crates.io-index" 1267 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 1268 | 1269 | [[package]] 1270 | name = "loop9" 1271 | version = "0.1.5" 1272 | source = "registry+https://github.com/rust-lang/crates.io-index" 1273 | checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" 1274 | dependencies = [ 1275 | "imgref", 1276 | ] 1277 | 1278 | [[package]] 1279 | name = "lru-slab" 1280 | version = "0.1.2" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 1283 | 1284 | [[package]] 1285 | name = "maybe-rayon" 1286 | version = "0.1.1" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" 1289 | dependencies = [ 1290 | "cfg-if", 1291 | "rayon", 1292 | ] 1293 | 1294 | [[package]] 1295 | name = "memchr" 1296 | version = "2.7.4" 1297 | source = "registry+https://github.com/rust-lang/crates.io-index" 1298 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1299 | 1300 | [[package]] 1301 | name = "mimalloc" 1302 | version = "0.1.46" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "995942f432bbb4822a7e9c3faa87a695185b0d09273ba85f097b54f4e458f2af" 1305 | dependencies = [ 1306 | "libmimalloc-sys", 1307 | ] 1308 | 1309 | [[package]] 1310 | name = "mime" 1311 | version = "0.3.17" 1312 | source = "registry+https://github.com/rust-lang/crates.io-index" 1313 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1314 | 1315 | [[package]] 1316 | name = "minimal-lexical" 1317 | version = "0.2.1" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1320 | 1321 | [[package]] 1322 | name = "miniz_oxide" 1323 | version = "0.8.8" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" 1326 | dependencies = [ 1327 | "adler2", 1328 | ] 1329 | 1330 | [[package]] 1331 | name = "mio" 1332 | version = "1.0.4" 1333 | source = "registry+https://github.com/rust-lang/crates.io-index" 1334 | checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 1335 | dependencies = [ 1336 | "libc", 1337 | "log", 1338 | "wasi 0.11.0+wasi-snapshot-preview1", 1339 | "windows-sys 0.59.0", 1340 | ] 1341 | 1342 | [[package]] 1343 | name = "nasm-rs" 1344 | version = "0.2.5" 1345 | source = "registry+https://github.com/rust-lang/crates.io-index" 1346 | checksum = "fe4d98d0065f4b1daf164b3eafb11974c94662e5e2396cf03f32d0bb5c17da51" 1347 | dependencies = [ 1348 | "rayon", 1349 | ] 1350 | 1351 | [[package]] 1352 | name = "native-tls" 1353 | version = "0.2.14" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 1356 | dependencies = [ 1357 | "libc", 1358 | "log", 1359 | "openssl", 1360 | "openssl-probe", 1361 | "openssl-sys", 1362 | "schannel", 1363 | "security-framework", 1364 | "security-framework-sys", 1365 | "tempfile", 1366 | ] 1367 | 1368 | [[package]] 1369 | name = "new_debug_unreachable" 1370 | version = "1.0.6" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 1373 | 1374 | [[package]] 1375 | name = "nom" 1376 | version = "7.1.3" 1377 | source = "registry+https://github.com/rust-lang/crates.io-index" 1378 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1379 | dependencies = [ 1380 | "memchr", 1381 | "minimal-lexical", 1382 | ] 1383 | 1384 | [[package]] 1385 | name = "noop_proc_macro" 1386 | version = "0.3.0" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" 1389 | 1390 | [[package]] 1391 | name = "num-bigint" 1392 | version = "0.4.6" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 1395 | dependencies = [ 1396 | "num-integer", 1397 | "num-traits", 1398 | ] 1399 | 1400 | [[package]] 1401 | name = "num-conv" 1402 | version = "0.1.0" 1403 | source = "registry+https://github.com/rust-lang/crates.io-index" 1404 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 1405 | 1406 | [[package]] 1407 | name = "num-derive" 1408 | version = "0.4.2" 1409 | source = "registry+https://github.com/rust-lang/crates.io-index" 1410 | checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" 1411 | dependencies = [ 1412 | "proc-macro2", 1413 | "quote", 1414 | "syn", 1415 | ] 1416 | 1417 | [[package]] 1418 | name = "num-integer" 1419 | version = "0.1.46" 1420 | source = "registry+https://github.com/rust-lang/crates.io-index" 1421 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 1422 | dependencies = [ 1423 | "num-traits", 1424 | ] 1425 | 1426 | [[package]] 1427 | name = "num-rational" 1428 | version = "0.4.2" 1429 | source = "registry+https://github.com/rust-lang/crates.io-index" 1430 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 1431 | dependencies = [ 1432 | "num-bigint", 1433 | "num-integer", 1434 | "num-traits", 1435 | ] 1436 | 1437 | [[package]] 1438 | name = "num-traits" 1439 | version = "0.2.19" 1440 | source = "registry+https://github.com/rust-lang/crates.io-index" 1441 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1442 | dependencies = [ 1443 | "autocfg", 1444 | ] 1445 | 1446 | [[package]] 1447 | name = "object" 1448 | version = "0.36.7" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1451 | dependencies = [ 1452 | "memchr", 1453 | ] 1454 | 1455 | [[package]] 1456 | name = "once_cell" 1457 | version = "1.21.3" 1458 | source = "registry+https://github.com/rust-lang/crates.io-index" 1459 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1460 | 1461 | [[package]] 1462 | name = "openssl" 1463 | version = "0.10.73" 1464 | source = "registry+https://github.com/rust-lang/crates.io-index" 1465 | checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" 1466 | dependencies = [ 1467 | "bitflags", 1468 | "cfg-if", 1469 | "foreign-types", 1470 | "libc", 1471 | "once_cell", 1472 | "openssl-macros", 1473 | "openssl-sys", 1474 | ] 1475 | 1476 | [[package]] 1477 | name = "openssl-macros" 1478 | version = "0.1.1" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1481 | dependencies = [ 1482 | "proc-macro2", 1483 | "quote", 1484 | "syn", 1485 | ] 1486 | 1487 | [[package]] 1488 | name = "openssl-probe" 1489 | version = "0.1.6" 1490 | source = "registry+https://github.com/rust-lang/crates.io-index" 1491 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1492 | 1493 | [[package]] 1494 | name = "openssl-sys" 1495 | version = "0.9.109" 1496 | source = "registry+https://github.com/rust-lang/crates.io-index" 1497 | checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" 1498 | dependencies = [ 1499 | "cc", 1500 | "libc", 1501 | "pkg-config", 1502 | "vcpkg", 1503 | ] 1504 | 1505 | [[package]] 1506 | name = "parking_lot" 1507 | version = "0.12.4" 1508 | source = "registry+https://github.com/rust-lang/crates.io-index" 1509 | checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" 1510 | dependencies = [ 1511 | "lock_api", 1512 | "parking_lot_core", 1513 | ] 1514 | 1515 | [[package]] 1516 | name = "parking_lot_core" 1517 | version = "0.9.11" 1518 | source = "registry+https://github.com/rust-lang/crates.io-index" 1519 | checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" 1520 | dependencies = [ 1521 | "cfg-if", 1522 | "libc", 1523 | "redox_syscall", 1524 | "smallvec", 1525 | "windows-targets", 1526 | ] 1527 | 1528 | [[package]] 1529 | name = "paste" 1530 | version = "1.0.15" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 1533 | 1534 | [[package]] 1535 | name = "percent-encoding" 1536 | version = "2.3.1" 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" 1538 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1539 | 1540 | [[package]] 1541 | name = "pin-project-lite" 1542 | version = "0.2.16" 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" 1544 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1545 | 1546 | [[package]] 1547 | name = "pin-utils" 1548 | version = "0.1.0" 1549 | source = "registry+https://github.com/rust-lang/crates.io-index" 1550 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1551 | 1552 | [[package]] 1553 | name = "piped-proxy" 1554 | version = "0.1.0" 1555 | dependencies = [ 1556 | "actix-web", 1557 | "blake3", 1558 | "bytes", 1559 | "futures-util", 1560 | "http 1.3.1", 1561 | "image", 1562 | "libwebp-sys", 1563 | "listenfd", 1564 | "mimalloc", 1565 | "once_cell", 1566 | "qstring", 1567 | "ravif", 1568 | "regex", 1569 | "reqwest", 1570 | "rgb", 1571 | "tokio", 1572 | ] 1573 | 1574 | [[package]] 1575 | name = "pkg-config" 1576 | version = "0.3.32" 1577 | source = "registry+https://github.com/rust-lang/crates.io-index" 1578 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1579 | 1580 | [[package]] 1581 | name = "potential_utf" 1582 | version = "0.1.2" 1583 | source = "registry+https://github.com/rust-lang/crates.io-index" 1584 | checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" 1585 | dependencies = [ 1586 | "zerovec", 1587 | ] 1588 | 1589 | [[package]] 1590 | name = "powerfmt" 1591 | version = "0.2.0" 1592 | source = "registry+https://github.com/rust-lang/crates.io-index" 1593 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1594 | 1595 | [[package]] 1596 | name = "ppv-lite86" 1597 | version = "0.2.21" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1600 | dependencies = [ 1601 | "zerocopy", 1602 | ] 1603 | 1604 | [[package]] 1605 | name = "proc-macro2" 1606 | version = "1.0.95" 1607 | source = "registry+https://github.com/rust-lang/crates.io-index" 1608 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 1609 | dependencies = [ 1610 | "unicode-ident", 1611 | ] 1612 | 1613 | [[package]] 1614 | name = "profiling" 1615 | version = "1.0.16" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" 1618 | dependencies = [ 1619 | "profiling-procmacros", 1620 | ] 1621 | 1622 | [[package]] 1623 | name = "profiling-procmacros" 1624 | version = "1.0.16" 1625 | source = "registry+https://github.com/rust-lang/crates.io-index" 1626 | checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" 1627 | dependencies = [ 1628 | "quote", 1629 | "syn", 1630 | ] 1631 | 1632 | [[package]] 1633 | name = "qstring" 1634 | version = "0.7.2" 1635 | source = "registry+https://github.com/rust-lang/crates.io-index" 1636 | checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" 1637 | dependencies = [ 1638 | "percent-encoding", 1639 | ] 1640 | 1641 | [[package]] 1642 | name = "quick-error" 1643 | version = "2.0.1" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" 1646 | 1647 | [[package]] 1648 | name = "quinn" 1649 | version = "0.11.8" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" 1652 | dependencies = [ 1653 | "bytes", 1654 | "cfg_aliases", 1655 | "pin-project-lite", 1656 | "quinn-proto", 1657 | "quinn-udp", 1658 | "rustc-hash", 1659 | "rustls", 1660 | "socket2", 1661 | "thiserror 2.0.12", 1662 | "tokio", 1663 | "tracing", 1664 | "web-time", 1665 | ] 1666 | 1667 | [[package]] 1668 | name = "quinn-proto" 1669 | version = "0.11.12" 1670 | source = "registry+https://github.com/rust-lang/crates.io-index" 1671 | checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" 1672 | dependencies = [ 1673 | "bytes", 1674 | "getrandom 0.3.3", 1675 | "lru-slab", 1676 | "rand 0.9.1", 1677 | "ring", 1678 | "rustc-hash", 1679 | "rustls", 1680 | "rustls-pki-types", 1681 | "slab", 1682 | "thiserror 2.0.12", 1683 | "tinyvec", 1684 | "tracing", 1685 | "web-time", 1686 | ] 1687 | 1688 | [[package]] 1689 | name = "quinn-udp" 1690 | version = "0.5.12" 1691 | source = "registry+https://github.com/rust-lang/crates.io-index" 1692 | checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" 1693 | dependencies = [ 1694 | "cfg_aliases", 1695 | "libc", 1696 | "once_cell", 1697 | "socket2", 1698 | "tracing", 1699 | "windows-sys 0.59.0", 1700 | ] 1701 | 1702 | [[package]] 1703 | name = "quote" 1704 | version = "1.0.40" 1705 | source = "registry+https://github.com/rust-lang/crates.io-index" 1706 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 1707 | dependencies = [ 1708 | "proc-macro2", 1709 | ] 1710 | 1711 | [[package]] 1712 | name = "r-efi" 1713 | version = "5.2.0" 1714 | source = "registry+https://github.com/rust-lang/crates.io-index" 1715 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 1716 | 1717 | [[package]] 1718 | name = "rand" 1719 | version = "0.8.5" 1720 | source = "registry+https://github.com/rust-lang/crates.io-index" 1721 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1722 | dependencies = [ 1723 | "libc", 1724 | "rand_chacha 0.3.1", 1725 | "rand_core 0.6.4", 1726 | ] 1727 | 1728 | [[package]] 1729 | name = "rand" 1730 | version = "0.9.1" 1731 | source = "registry+https://github.com/rust-lang/crates.io-index" 1732 | checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" 1733 | dependencies = [ 1734 | "rand_chacha 0.9.0", 1735 | "rand_core 0.9.3", 1736 | ] 1737 | 1738 | [[package]] 1739 | name = "rand_chacha" 1740 | version = "0.3.1" 1741 | source = "registry+https://github.com/rust-lang/crates.io-index" 1742 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1743 | dependencies = [ 1744 | "ppv-lite86", 1745 | "rand_core 0.6.4", 1746 | ] 1747 | 1748 | [[package]] 1749 | name = "rand_chacha" 1750 | version = "0.9.0" 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" 1752 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 1753 | dependencies = [ 1754 | "ppv-lite86", 1755 | "rand_core 0.9.3", 1756 | ] 1757 | 1758 | [[package]] 1759 | name = "rand_core" 1760 | version = "0.6.4" 1761 | source = "registry+https://github.com/rust-lang/crates.io-index" 1762 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1763 | dependencies = [ 1764 | "getrandom 0.2.16", 1765 | ] 1766 | 1767 | [[package]] 1768 | name = "rand_core" 1769 | version = "0.9.3" 1770 | source = "registry+https://github.com/rust-lang/crates.io-index" 1771 | checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 1772 | dependencies = [ 1773 | "getrandom 0.3.3", 1774 | ] 1775 | 1776 | [[package]] 1777 | name = "rav1e" 1778 | version = "0.7.1" 1779 | source = "registry+https://github.com/rust-lang/crates.io-index" 1780 | checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" 1781 | dependencies = [ 1782 | "arbitrary", 1783 | "arg_enum_proc_macro", 1784 | "arrayvec", 1785 | "av1-grain", 1786 | "bitstream-io", 1787 | "built", 1788 | "cc", 1789 | "cfg-if", 1790 | "interpolate_name", 1791 | "itertools", 1792 | "libc", 1793 | "libfuzzer-sys", 1794 | "log", 1795 | "maybe-rayon", 1796 | "nasm-rs", 1797 | "new_debug_unreachable", 1798 | "noop_proc_macro", 1799 | "num-derive", 1800 | "num-traits", 1801 | "once_cell", 1802 | "paste", 1803 | "profiling", 1804 | "rand 0.8.5", 1805 | "rand_chacha 0.3.1", 1806 | "simd_helpers", 1807 | "system-deps", 1808 | "thiserror 1.0.69", 1809 | "v_frame", 1810 | "wasm-bindgen", 1811 | ] 1812 | 1813 | [[package]] 1814 | name = "ravif" 1815 | version = "0.11.12" 1816 | source = "registry+https://github.com/rust-lang/crates.io-index" 1817 | checksum = "d6a5f31fcf7500f9401fea858ea4ab5525c99f2322cfcee732c0e6c74208c0c6" 1818 | dependencies = [ 1819 | "avif-serialize", 1820 | "imgref", 1821 | "loop9", 1822 | "quick-error", 1823 | "rav1e", 1824 | "rayon", 1825 | "rgb", 1826 | ] 1827 | 1828 | [[package]] 1829 | name = "rayon" 1830 | version = "1.10.0" 1831 | source = "registry+https://github.com/rust-lang/crates.io-index" 1832 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 1833 | dependencies = [ 1834 | "either", 1835 | "rayon-core", 1836 | ] 1837 | 1838 | [[package]] 1839 | name = "rayon-core" 1840 | version = "1.12.1" 1841 | source = "registry+https://github.com/rust-lang/crates.io-index" 1842 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 1843 | dependencies = [ 1844 | "crossbeam-deque", 1845 | "crossbeam-utils", 1846 | ] 1847 | 1848 | [[package]] 1849 | name = "redox_syscall" 1850 | version = "0.5.12" 1851 | source = "registry+https://github.com/rust-lang/crates.io-index" 1852 | checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" 1853 | dependencies = [ 1854 | "bitflags", 1855 | ] 1856 | 1857 | [[package]] 1858 | name = "regex" 1859 | version = "1.11.1" 1860 | source = "registry+https://github.com/rust-lang/crates.io-index" 1861 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 1862 | dependencies = [ 1863 | "aho-corasick", 1864 | "memchr", 1865 | "regex-automata", 1866 | "regex-syntax", 1867 | ] 1868 | 1869 | [[package]] 1870 | name = "regex-automata" 1871 | version = "0.4.9" 1872 | source = "registry+https://github.com/rust-lang/crates.io-index" 1873 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 1874 | dependencies = [ 1875 | "aho-corasick", 1876 | "memchr", 1877 | "regex-syntax", 1878 | ] 1879 | 1880 | [[package]] 1881 | name = "regex-lite" 1882 | version = "0.1.6" 1883 | source = "registry+https://github.com/rust-lang/crates.io-index" 1884 | checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" 1885 | 1886 | [[package]] 1887 | name = "regex-syntax" 1888 | version = "0.8.5" 1889 | source = "registry+https://github.com/rust-lang/crates.io-index" 1890 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 1891 | 1892 | [[package]] 1893 | name = "reqwest" 1894 | version = "0.12.19" 1895 | source = "registry+https://github.com/rust-lang/crates.io-index" 1896 | checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" 1897 | dependencies = [ 1898 | "async-compression", 1899 | "base64", 1900 | "bytes", 1901 | "futures-core", 1902 | "futures-util", 1903 | "http 1.3.1", 1904 | "http-body", 1905 | "http-body-util", 1906 | "hyper", 1907 | "hyper-rustls", 1908 | "hyper-tls", 1909 | "hyper-util", 1910 | "ipnet", 1911 | "js-sys", 1912 | "log", 1913 | "mime", 1914 | "native-tls", 1915 | "once_cell", 1916 | "percent-encoding", 1917 | "pin-project-lite", 1918 | "quinn", 1919 | "rustls", 1920 | "rustls-pki-types", 1921 | "serde", 1922 | "serde_json", 1923 | "serde_urlencoded", 1924 | "sync_wrapper", 1925 | "tokio", 1926 | "tokio-native-tls", 1927 | "tokio-rustls", 1928 | "tokio-socks", 1929 | "tokio-util", 1930 | "tower", 1931 | "tower-http", 1932 | "tower-service", 1933 | "url", 1934 | "wasm-bindgen", 1935 | "wasm-bindgen-futures", 1936 | "wasm-streams", 1937 | "web-sys", 1938 | "webpki-roots", 1939 | ] 1940 | 1941 | [[package]] 1942 | name = "rgb" 1943 | version = "0.8.50" 1944 | source = "registry+https://github.com/rust-lang/crates.io-index" 1945 | checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" 1946 | dependencies = [ 1947 | "bytemuck", 1948 | ] 1949 | 1950 | [[package]] 1951 | name = "ring" 1952 | version = "0.17.14" 1953 | source = "registry+https://github.com/rust-lang/crates.io-index" 1954 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1955 | dependencies = [ 1956 | "cc", 1957 | "cfg-if", 1958 | "getrandom 0.2.16", 1959 | "libc", 1960 | "untrusted", 1961 | "windows-sys 0.52.0", 1962 | ] 1963 | 1964 | [[package]] 1965 | name = "rustc-demangle" 1966 | version = "0.1.24" 1967 | source = "registry+https://github.com/rust-lang/crates.io-index" 1968 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1969 | 1970 | [[package]] 1971 | name = "rustc-hash" 1972 | version = "2.1.1" 1973 | source = "registry+https://github.com/rust-lang/crates.io-index" 1974 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 1975 | 1976 | [[package]] 1977 | name = "rustix" 1978 | version = "1.0.7" 1979 | source = "registry+https://github.com/rust-lang/crates.io-index" 1980 | checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" 1981 | dependencies = [ 1982 | "bitflags", 1983 | "errno", 1984 | "libc", 1985 | "linux-raw-sys", 1986 | "windows-sys 0.59.0", 1987 | ] 1988 | 1989 | [[package]] 1990 | name = "rustls" 1991 | version = "0.23.27" 1992 | source = "registry+https://github.com/rust-lang/crates.io-index" 1993 | checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" 1994 | dependencies = [ 1995 | "once_cell", 1996 | "ring", 1997 | "rustls-pki-types", 1998 | "rustls-webpki", 1999 | "subtle", 2000 | "zeroize", 2001 | ] 2002 | 2003 | [[package]] 2004 | name = "rustls-pki-types" 2005 | version = "1.12.0" 2006 | source = "registry+https://github.com/rust-lang/crates.io-index" 2007 | checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 2008 | dependencies = [ 2009 | "web-time", 2010 | "zeroize", 2011 | ] 2012 | 2013 | [[package]] 2014 | name = "rustls-webpki" 2015 | version = "0.103.3" 2016 | source = "registry+https://github.com/rust-lang/crates.io-index" 2017 | checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" 2018 | dependencies = [ 2019 | "ring", 2020 | "rustls-pki-types", 2021 | "untrusted", 2022 | ] 2023 | 2024 | [[package]] 2025 | name = "rustversion" 2026 | version = "1.0.21" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" 2029 | 2030 | [[package]] 2031 | name = "ryu" 2032 | version = "1.0.20" 2033 | source = "registry+https://github.com/rust-lang/crates.io-index" 2034 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 2035 | 2036 | [[package]] 2037 | name = "schannel" 2038 | version = "0.1.27" 2039 | source = "registry+https://github.com/rust-lang/crates.io-index" 2040 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 2041 | dependencies = [ 2042 | "windows-sys 0.59.0", 2043 | ] 2044 | 2045 | [[package]] 2046 | name = "scopeguard" 2047 | version = "1.2.0" 2048 | source = "registry+https://github.com/rust-lang/crates.io-index" 2049 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2050 | 2051 | [[package]] 2052 | name = "security-framework" 2053 | version = "2.11.1" 2054 | source = "registry+https://github.com/rust-lang/crates.io-index" 2055 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 2056 | dependencies = [ 2057 | "bitflags", 2058 | "core-foundation", 2059 | "core-foundation-sys", 2060 | "libc", 2061 | "security-framework-sys", 2062 | ] 2063 | 2064 | [[package]] 2065 | name = "security-framework-sys" 2066 | version = "2.14.0" 2067 | source = "registry+https://github.com/rust-lang/crates.io-index" 2068 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 2069 | dependencies = [ 2070 | "core-foundation-sys", 2071 | "libc", 2072 | ] 2073 | 2074 | [[package]] 2075 | name = "serde" 2076 | version = "1.0.219" 2077 | source = "registry+https://github.com/rust-lang/crates.io-index" 2078 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 2079 | dependencies = [ 2080 | "serde_derive", 2081 | ] 2082 | 2083 | [[package]] 2084 | name = "serde_derive" 2085 | version = "1.0.219" 2086 | source = "registry+https://github.com/rust-lang/crates.io-index" 2087 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 2088 | dependencies = [ 2089 | "proc-macro2", 2090 | "quote", 2091 | "syn", 2092 | ] 2093 | 2094 | [[package]] 2095 | name = "serde_json" 2096 | version = "1.0.140" 2097 | source = "registry+https://github.com/rust-lang/crates.io-index" 2098 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 2099 | dependencies = [ 2100 | "itoa", 2101 | "memchr", 2102 | "ryu", 2103 | "serde", 2104 | ] 2105 | 2106 | [[package]] 2107 | name = "serde_spanned" 2108 | version = "0.6.8" 2109 | source = "registry+https://github.com/rust-lang/crates.io-index" 2110 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 2111 | dependencies = [ 2112 | "serde", 2113 | ] 2114 | 2115 | [[package]] 2116 | name = "serde_urlencoded" 2117 | version = "0.7.1" 2118 | source = "registry+https://github.com/rust-lang/crates.io-index" 2119 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2120 | dependencies = [ 2121 | "form_urlencoded", 2122 | "itoa", 2123 | "ryu", 2124 | "serde", 2125 | ] 2126 | 2127 | [[package]] 2128 | name = "sha1" 2129 | version = "0.10.6" 2130 | source = "registry+https://github.com/rust-lang/crates.io-index" 2131 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 2132 | dependencies = [ 2133 | "cfg-if", 2134 | "cpufeatures", 2135 | "digest", 2136 | ] 2137 | 2138 | [[package]] 2139 | name = "shlex" 2140 | version = "1.3.0" 2141 | source = "registry+https://github.com/rust-lang/crates.io-index" 2142 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2143 | 2144 | [[package]] 2145 | name = "signal-hook-registry" 2146 | version = "1.4.5" 2147 | source = "registry+https://github.com/rust-lang/crates.io-index" 2148 | checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" 2149 | dependencies = [ 2150 | "libc", 2151 | ] 2152 | 2153 | [[package]] 2154 | name = "simd_helpers" 2155 | version = "0.1.0" 2156 | source = "registry+https://github.com/rust-lang/crates.io-index" 2157 | checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" 2158 | dependencies = [ 2159 | "quote", 2160 | ] 2161 | 2162 | [[package]] 2163 | name = "slab" 2164 | version = "0.4.9" 2165 | source = "registry+https://github.com/rust-lang/crates.io-index" 2166 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 2167 | dependencies = [ 2168 | "autocfg", 2169 | ] 2170 | 2171 | [[package]] 2172 | name = "smallvec" 2173 | version = "1.15.0" 2174 | source = "registry+https://github.com/rust-lang/crates.io-index" 2175 | checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 2176 | 2177 | [[package]] 2178 | name = "socket2" 2179 | version = "0.5.10" 2180 | source = "registry+https://github.com/rust-lang/crates.io-index" 2181 | checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 2182 | dependencies = [ 2183 | "libc", 2184 | "windows-sys 0.52.0", 2185 | ] 2186 | 2187 | [[package]] 2188 | name = "stable_deref_trait" 2189 | version = "1.2.0" 2190 | source = "registry+https://github.com/rust-lang/crates.io-index" 2191 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2192 | 2193 | [[package]] 2194 | name = "subtle" 2195 | version = "2.6.1" 2196 | source = "registry+https://github.com/rust-lang/crates.io-index" 2197 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2198 | 2199 | [[package]] 2200 | name = "syn" 2201 | version = "2.0.101" 2202 | source = "registry+https://github.com/rust-lang/crates.io-index" 2203 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 2204 | dependencies = [ 2205 | "proc-macro2", 2206 | "quote", 2207 | "unicode-ident", 2208 | ] 2209 | 2210 | [[package]] 2211 | name = "sync_wrapper" 2212 | version = "1.0.2" 2213 | source = "registry+https://github.com/rust-lang/crates.io-index" 2214 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 2215 | dependencies = [ 2216 | "futures-core", 2217 | ] 2218 | 2219 | [[package]] 2220 | name = "synstructure" 2221 | version = "0.13.2" 2222 | source = "registry+https://github.com/rust-lang/crates.io-index" 2223 | checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 2224 | dependencies = [ 2225 | "proc-macro2", 2226 | "quote", 2227 | "syn", 2228 | ] 2229 | 2230 | [[package]] 2231 | name = "system-deps" 2232 | version = "6.2.2" 2233 | source = "registry+https://github.com/rust-lang/crates.io-index" 2234 | checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" 2235 | dependencies = [ 2236 | "cfg-expr", 2237 | "heck", 2238 | "pkg-config", 2239 | "toml", 2240 | "version-compare", 2241 | ] 2242 | 2243 | [[package]] 2244 | name = "target-lexicon" 2245 | version = "0.12.16" 2246 | source = "registry+https://github.com/rust-lang/crates.io-index" 2247 | checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" 2248 | 2249 | [[package]] 2250 | name = "tempfile" 2251 | version = "3.20.0" 2252 | source = "registry+https://github.com/rust-lang/crates.io-index" 2253 | checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" 2254 | dependencies = [ 2255 | "fastrand", 2256 | "getrandom 0.3.3", 2257 | "once_cell", 2258 | "rustix", 2259 | "windows-sys 0.59.0", 2260 | ] 2261 | 2262 | [[package]] 2263 | name = "thiserror" 2264 | version = "1.0.69" 2265 | source = "registry+https://github.com/rust-lang/crates.io-index" 2266 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 2267 | dependencies = [ 2268 | "thiserror-impl 1.0.69", 2269 | ] 2270 | 2271 | [[package]] 2272 | name = "thiserror" 2273 | version = "2.0.12" 2274 | source = "registry+https://github.com/rust-lang/crates.io-index" 2275 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 2276 | dependencies = [ 2277 | "thiserror-impl 2.0.12", 2278 | ] 2279 | 2280 | [[package]] 2281 | name = "thiserror-impl" 2282 | version = "1.0.69" 2283 | source = "registry+https://github.com/rust-lang/crates.io-index" 2284 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 2285 | dependencies = [ 2286 | "proc-macro2", 2287 | "quote", 2288 | "syn", 2289 | ] 2290 | 2291 | [[package]] 2292 | name = "thiserror-impl" 2293 | version = "2.0.12" 2294 | source = "registry+https://github.com/rust-lang/crates.io-index" 2295 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 2296 | dependencies = [ 2297 | "proc-macro2", 2298 | "quote", 2299 | "syn", 2300 | ] 2301 | 2302 | [[package]] 2303 | name = "time" 2304 | version = "0.3.41" 2305 | source = "registry+https://github.com/rust-lang/crates.io-index" 2306 | checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" 2307 | dependencies = [ 2308 | "deranged", 2309 | "itoa", 2310 | "num-conv", 2311 | "powerfmt", 2312 | "serde", 2313 | "time-core", 2314 | "time-macros", 2315 | ] 2316 | 2317 | [[package]] 2318 | name = "time-core" 2319 | version = "0.1.4" 2320 | source = "registry+https://github.com/rust-lang/crates.io-index" 2321 | checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" 2322 | 2323 | [[package]] 2324 | name = "time-macros" 2325 | version = "0.2.22" 2326 | source = "registry+https://github.com/rust-lang/crates.io-index" 2327 | checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" 2328 | dependencies = [ 2329 | "num-conv", 2330 | "time-core", 2331 | ] 2332 | 2333 | [[package]] 2334 | name = "tinystr" 2335 | version = "0.8.1" 2336 | source = "registry+https://github.com/rust-lang/crates.io-index" 2337 | checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 2338 | dependencies = [ 2339 | "displaydoc", 2340 | "zerovec", 2341 | ] 2342 | 2343 | [[package]] 2344 | name = "tinyvec" 2345 | version = "1.9.0" 2346 | source = "registry+https://github.com/rust-lang/crates.io-index" 2347 | checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" 2348 | dependencies = [ 2349 | "tinyvec_macros", 2350 | ] 2351 | 2352 | [[package]] 2353 | name = "tinyvec_macros" 2354 | version = "0.1.1" 2355 | source = "registry+https://github.com/rust-lang/crates.io-index" 2356 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 2357 | 2358 | [[package]] 2359 | name = "tokio" 2360 | version = "1.45.1" 2361 | source = "registry+https://github.com/rust-lang/crates.io-index" 2362 | checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" 2363 | dependencies = [ 2364 | "backtrace", 2365 | "bytes", 2366 | "libc", 2367 | "mio", 2368 | "parking_lot", 2369 | "pin-project-lite", 2370 | "signal-hook-registry", 2371 | "socket2", 2372 | "tokio-macros", 2373 | "windows-sys 0.52.0", 2374 | ] 2375 | 2376 | [[package]] 2377 | name = "tokio-macros" 2378 | version = "2.5.0" 2379 | source = "registry+https://github.com/rust-lang/crates.io-index" 2380 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 2381 | dependencies = [ 2382 | "proc-macro2", 2383 | "quote", 2384 | "syn", 2385 | ] 2386 | 2387 | [[package]] 2388 | name = "tokio-native-tls" 2389 | version = "0.3.1" 2390 | source = "registry+https://github.com/rust-lang/crates.io-index" 2391 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 2392 | dependencies = [ 2393 | "native-tls", 2394 | "tokio", 2395 | ] 2396 | 2397 | [[package]] 2398 | name = "tokio-rustls" 2399 | version = "0.26.2" 2400 | source = "registry+https://github.com/rust-lang/crates.io-index" 2401 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 2402 | dependencies = [ 2403 | "rustls", 2404 | "tokio", 2405 | ] 2406 | 2407 | [[package]] 2408 | name = "tokio-socks" 2409 | version = "0.5.2" 2410 | source = "registry+https://github.com/rust-lang/crates.io-index" 2411 | checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" 2412 | dependencies = [ 2413 | "either", 2414 | "futures-util", 2415 | "thiserror 1.0.69", 2416 | "tokio", 2417 | ] 2418 | 2419 | [[package]] 2420 | name = "tokio-util" 2421 | version = "0.7.15" 2422 | source = "registry+https://github.com/rust-lang/crates.io-index" 2423 | checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" 2424 | dependencies = [ 2425 | "bytes", 2426 | "futures-core", 2427 | "futures-sink", 2428 | "pin-project-lite", 2429 | "tokio", 2430 | ] 2431 | 2432 | [[package]] 2433 | name = "toml" 2434 | version = "0.8.22" 2435 | source = "registry+https://github.com/rust-lang/crates.io-index" 2436 | checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" 2437 | dependencies = [ 2438 | "serde", 2439 | "serde_spanned", 2440 | "toml_datetime", 2441 | "toml_edit", 2442 | ] 2443 | 2444 | [[package]] 2445 | name = "toml_datetime" 2446 | version = "0.6.9" 2447 | source = "registry+https://github.com/rust-lang/crates.io-index" 2448 | checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" 2449 | dependencies = [ 2450 | "serde", 2451 | ] 2452 | 2453 | [[package]] 2454 | name = "toml_edit" 2455 | version = "0.22.26" 2456 | source = "registry+https://github.com/rust-lang/crates.io-index" 2457 | checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" 2458 | dependencies = [ 2459 | "indexmap", 2460 | "serde", 2461 | "serde_spanned", 2462 | "toml_datetime", 2463 | "winnow", 2464 | ] 2465 | 2466 | [[package]] 2467 | name = "tower" 2468 | version = "0.5.2" 2469 | source = "registry+https://github.com/rust-lang/crates.io-index" 2470 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 2471 | dependencies = [ 2472 | "futures-core", 2473 | "futures-util", 2474 | "pin-project-lite", 2475 | "sync_wrapper", 2476 | "tokio", 2477 | "tower-layer", 2478 | "tower-service", 2479 | ] 2480 | 2481 | [[package]] 2482 | name = "tower-http" 2483 | version = "0.6.5" 2484 | source = "registry+https://github.com/rust-lang/crates.io-index" 2485 | checksum = "5cc2d9e086a412a451384326f521c8123a99a466b329941a9403696bff9b0da2" 2486 | dependencies = [ 2487 | "bitflags", 2488 | "bytes", 2489 | "futures-util", 2490 | "http 1.3.1", 2491 | "http-body", 2492 | "iri-string", 2493 | "pin-project-lite", 2494 | "tower", 2495 | "tower-layer", 2496 | "tower-service", 2497 | ] 2498 | 2499 | [[package]] 2500 | name = "tower-layer" 2501 | version = "0.3.3" 2502 | source = "registry+https://github.com/rust-lang/crates.io-index" 2503 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 2504 | 2505 | [[package]] 2506 | name = "tower-service" 2507 | version = "0.3.3" 2508 | source = "registry+https://github.com/rust-lang/crates.io-index" 2509 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2510 | 2511 | [[package]] 2512 | name = "tracing" 2513 | version = "0.1.41" 2514 | source = "registry+https://github.com/rust-lang/crates.io-index" 2515 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 2516 | dependencies = [ 2517 | "log", 2518 | "pin-project-lite", 2519 | "tracing-attributes", 2520 | "tracing-core", 2521 | ] 2522 | 2523 | [[package]] 2524 | name = "tracing-attributes" 2525 | version = "0.1.28" 2526 | source = "registry+https://github.com/rust-lang/crates.io-index" 2527 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 2528 | dependencies = [ 2529 | "proc-macro2", 2530 | "quote", 2531 | "syn", 2532 | ] 2533 | 2534 | [[package]] 2535 | name = "tracing-core" 2536 | version = "0.1.33" 2537 | source = "registry+https://github.com/rust-lang/crates.io-index" 2538 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 2539 | dependencies = [ 2540 | "once_cell", 2541 | ] 2542 | 2543 | [[package]] 2544 | name = "try-lock" 2545 | version = "0.2.5" 2546 | source = "registry+https://github.com/rust-lang/crates.io-index" 2547 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2548 | 2549 | [[package]] 2550 | name = "typenum" 2551 | version = "1.18.0" 2552 | source = "registry+https://github.com/rust-lang/crates.io-index" 2553 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 2554 | 2555 | [[package]] 2556 | name = "unicode-ident" 2557 | version = "1.0.18" 2558 | source = "registry+https://github.com/rust-lang/crates.io-index" 2559 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 2560 | 2561 | [[package]] 2562 | name = "unicode-xid" 2563 | version = "0.2.6" 2564 | source = "registry+https://github.com/rust-lang/crates.io-index" 2565 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 2566 | 2567 | [[package]] 2568 | name = "untrusted" 2569 | version = "0.9.0" 2570 | source = "registry+https://github.com/rust-lang/crates.io-index" 2571 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2572 | 2573 | [[package]] 2574 | name = "url" 2575 | version = "2.5.4" 2576 | source = "registry+https://github.com/rust-lang/crates.io-index" 2577 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 2578 | dependencies = [ 2579 | "form_urlencoded", 2580 | "idna", 2581 | "percent-encoding", 2582 | ] 2583 | 2584 | [[package]] 2585 | name = "utf8_iter" 2586 | version = "1.0.4" 2587 | source = "registry+https://github.com/rust-lang/crates.io-index" 2588 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2589 | 2590 | [[package]] 2591 | name = "uuid" 2592 | version = "1.17.0" 2593 | source = "registry+https://github.com/rust-lang/crates.io-index" 2594 | checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" 2595 | dependencies = [ 2596 | "js-sys", 2597 | "wasm-bindgen", 2598 | ] 2599 | 2600 | [[package]] 2601 | name = "v_frame" 2602 | version = "0.3.8" 2603 | source = "registry+https://github.com/rust-lang/crates.io-index" 2604 | checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" 2605 | dependencies = [ 2606 | "aligned-vec", 2607 | "num-traits", 2608 | "wasm-bindgen", 2609 | ] 2610 | 2611 | [[package]] 2612 | name = "vcpkg" 2613 | version = "0.2.15" 2614 | source = "registry+https://github.com/rust-lang/crates.io-index" 2615 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2616 | 2617 | [[package]] 2618 | name = "version-compare" 2619 | version = "0.2.0" 2620 | source = "registry+https://github.com/rust-lang/crates.io-index" 2621 | checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" 2622 | 2623 | [[package]] 2624 | name = "version_check" 2625 | version = "0.9.5" 2626 | source = "registry+https://github.com/rust-lang/crates.io-index" 2627 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2628 | 2629 | [[package]] 2630 | name = "want" 2631 | version = "0.3.1" 2632 | source = "registry+https://github.com/rust-lang/crates.io-index" 2633 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2634 | dependencies = [ 2635 | "try-lock", 2636 | ] 2637 | 2638 | [[package]] 2639 | name = "wasi" 2640 | version = "0.11.0+wasi-snapshot-preview1" 2641 | source = "registry+https://github.com/rust-lang/crates.io-index" 2642 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2643 | 2644 | [[package]] 2645 | name = "wasi" 2646 | version = "0.14.2+wasi-0.2.4" 2647 | source = "registry+https://github.com/rust-lang/crates.io-index" 2648 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 2649 | dependencies = [ 2650 | "wit-bindgen-rt", 2651 | ] 2652 | 2653 | [[package]] 2654 | name = "wasm-bindgen" 2655 | version = "0.2.100" 2656 | source = "registry+https://github.com/rust-lang/crates.io-index" 2657 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 2658 | dependencies = [ 2659 | "cfg-if", 2660 | "once_cell", 2661 | "rustversion", 2662 | "wasm-bindgen-macro", 2663 | ] 2664 | 2665 | [[package]] 2666 | name = "wasm-bindgen-backend" 2667 | version = "0.2.100" 2668 | source = "registry+https://github.com/rust-lang/crates.io-index" 2669 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 2670 | dependencies = [ 2671 | "bumpalo", 2672 | "log", 2673 | "proc-macro2", 2674 | "quote", 2675 | "syn", 2676 | "wasm-bindgen-shared", 2677 | ] 2678 | 2679 | [[package]] 2680 | name = "wasm-bindgen-futures" 2681 | version = "0.4.50" 2682 | source = "registry+https://github.com/rust-lang/crates.io-index" 2683 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 2684 | dependencies = [ 2685 | "cfg-if", 2686 | "js-sys", 2687 | "once_cell", 2688 | "wasm-bindgen", 2689 | "web-sys", 2690 | ] 2691 | 2692 | [[package]] 2693 | name = "wasm-bindgen-macro" 2694 | version = "0.2.100" 2695 | source = "registry+https://github.com/rust-lang/crates.io-index" 2696 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 2697 | dependencies = [ 2698 | "quote", 2699 | "wasm-bindgen-macro-support", 2700 | ] 2701 | 2702 | [[package]] 2703 | name = "wasm-bindgen-macro-support" 2704 | version = "0.2.100" 2705 | source = "registry+https://github.com/rust-lang/crates.io-index" 2706 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 2707 | dependencies = [ 2708 | "proc-macro2", 2709 | "quote", 2710 | "syn", 2711 | "wasm-bindgen-backend", 2712 | "wasm-bindgen-shared", 2713 | ] 2714 | 2715 | [[package]] 2716 | name = "wasm-bindgen-shared" 2717 | version = "0.2.100" 2718 | source = "registry+https://github.com/rust-lang/crates.io-index" 2719 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 2720 | dependencies = [ 2721 | "unicode-ident", 2722 | ] 2723 | 2724 | [[package]] 2725 | name = "wasm-streams" 2726 | version = "0.4.2" 2727 | source = "registry+https://github.com/rust-lang/crates.io-index" 2728 | checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" 2729 | dependencies = [ 2730 | "futures-util", 2731 | "js-sys", 2732 | "wasm-bindgen", 2733 | "wasm-bindgen-futures", 2734 | "web-sys", 2735 | ] 2736 | 2737 | [[package]] 2738 | name = "web-sys" 2739 | version = "0.3.77" 2740 | source = "registry+https://github.com/rust-lang/crates.io-index" 2741 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 2742 | dependencies = [ 2743 | "js-sys", 2744 | "wasm-bindgen", 2745 | ] 2746 | 2747 | [[package]] 2748 | name = "web-time" 2749 | version = "1.1.0" 2750 | source = "registry+https://github.com/rust-lang/crates.io-index" 2751 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2752 | dependencies = [ 2753 | "js-sys", 2754 | "wasm-bindgen", 2755 | ] 2756 | 2757 | [[package]] 2758 | name = "webpki-roots" 2759 | version = "1.0.0" 2760 | source = "registry+https://github.com/rust-lang/crates.io-index" 2761 | checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" 2762 | dependencies = [ 2763 | "rustls-pki-types", 2764 | ] 2765 | 2766 | [[package]] 2767 | name = "winapi" 2768 | version = "0.3.9" 2769 | source = "registry+https://github.com/rust-lang/crates.io-index" 2770 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2771 | dependencies = [ 2772 | "winapi-i686-pc-windows-gnu", 2773 | "winapi-x86_64-pc-windows-gnu", 2774 | ] 2775 | 2776 | [[package]] 2777 | name = "winapi-i686-pc-windows-gnu" 2778 | version = "0.4.0" 2779 | source = "registry+https://github.com/rust-lang/crates.io-index" 2780 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2781 | 2782 | [[package]] 2783 | name = "winapi-x86_64-pc-windows-gnu" 2784 | version = "0.4.0" 2785 | source = "registry+https://github.com/rust-lang/crates.io-index" 2786 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2787 | 2788 | [[package]] 2789 | name = "windows-sys" 2790 | version = "0.52.0" 2791 | source = "registry+https://github.com/rust-lang/crates.io-index" 2792 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2793 | dependencies = [ 2794 | "windows-targets", 2795 | ] 2796 | 2797 | [[package]] 2798 | name = "windows-sys" 2799 | version = "0.59.0" 2800 | source = "registry+https://github.com/rust-lang/crates.io-index" 2801 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2802 | dependencies = [ 2803 | "windows-targets", 2804 | ] 2805 | 2806 | [[package]] 2807 | name = "windows-targets" 2808 | version = "0.52.6" 2809 | source = "registry+https://github.com/rust-lang/crates.io-index" 2810 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2811 | dependencies = [ 2812 | "windows_aarch64_gnullvm", 2813 | "windows_aarch64_msvc", 2814 | "windows_i686_gnu", 2815 | "windows_i686_gnullvm", 2816 | "windows_i686_msvc", 2817 | "windows_x86_64_gnu", 2818 | "windows_x86_64_gnullvm", 2819 | "windows_x86_64_msvc", 2820 | ] 2821 | 2822 | [[package]] 2823 | name = "windows_aarch64_gnullvm" 2824 | version = "0.52.6" 2825 | source = "registry+https://github.com/rust-lang/crates.io-index" 2826 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2827 | 2828 | [[package]] 2829 | name = "windows_aarch64_msvc" 2830 | version = "0.52.6" 2831 | source = "registry+https://github.com/rust-lang/crates.io-index" 2832 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2833 | 2834 | [[package]] 2835 | name = "windows_i686_gnu" 2836 | version = "0.52.6" 2837 | source = "registry+https://github.com/rust-lang/crates.io-index" 2838 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2839 | 2840 | [[package]] 2841 | name = "windows_i686_gnullvm" 2842 | version = "0.52.6" 2843 | source = "registry+https://github.com/rust-lang/crates.io-index" 2844 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2845 | 2846 | [[package]] 2847 | name = "windows_i686_msvc" 2848 | version = "0.52.6" 2849 | source = "registry+https://github.com/rust-lang/crates.io-index" 2850 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2851 | 2852 | [[package]] 2853 | name = "windows_x86_64_gnu" 2854 | version = "0.52.6" 2855 | source = "registry+https://github.com/rust-lang/crates.io-index" 2856 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2857 | 2858 | [[package]] 2859 | name = "windows_x86_64_gnullvm" 2860 | version = "0.52.6" 2861 | source = "registry+https://github.com/rust-lang/crates.io-index" 2862 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2863 | 2864 | [[package]] 2865 | name = "windows_x86_64_msvc" 2866 | version = "0.52.6" 2867 | source = "registry+https://github.com/rust-lang/crates.io-index" 2868 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2869 | 2870 | [[package]] 2871 | name = "winnow" 2872 | version = "0.7.10" 2873 | source = "registry+https://github.com/rust-lang/crates.io-index" 2874 | checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" 2875 | dependencies = [ 2876 | "memchr", 2877 | ] 2878 | 2879 | [[package]] 2880 | name = "wit-bindgen-rt" 2881 | version = "0.39.0" 2882 | source = "registry+https://github.com/rust-lang/crates.io-index" 2883 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 2884 | dependencies = [ 2885 | "bitflags", 2886 | ] 2887 | 2888 | [[package]] 2889 | name = "writeable" 2890 | version = "0.6.1" 2891 | source = "registry+https://github.com/rust-lang/crates.io-index" 2892 | checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 2893 | 2894 | [[package]] 2895 | name = "yoke" 2896 | version = "0.8.0" 2897 | source = "registry+https://github.com/rust-lang/crates.io-index" 2898 | checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 2899 | dependencies = [ 2900 | "serde", 2901 | "stable_deref_trait", 2902 | "yoke-derive", 2903 | "zerofrom", 2904 | ] 2905 | 2906 | [[package]] 2907 | name = "yoke-derive" 2908 | version = "0.8.0" 2909 | source = "registry+https://github.com/rust-lang/crates.io-index" 2910 | checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 2911 | dependencies = [ 2912 | "proc-macro2", 2913 | "quote", 2914 | "syn", 2915 | "synstructure", 2916 | ] 2917 | 2918 | [[package]] 2919 | name = "zerocopy" 2920 | version = "0.8.25" 2921 | source = "registry+https://github.com/rust-lang/crates.io-index" 2922 | checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" 2923 | dependencies = [ 2924 | "zerocopy-derive", 2925 | ] 2926 | 2927 | [[package]] 2928 | name = "zerocopy-derive" 2929 | version = "0.8.25" 2930 | source = "registry+https://github.com/rust-lang/crates.io-index" 2931 | checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" 2932 | dependencies = [ 2933 | "proc-macro2", 2934 | "quote", 2935 | "syn", 2936 | ] 2937 | 2938 | [[package]] 2939 | name = "zerofrom" 2940 | version = "0.1.6" 2941 | source = "registry+https://github.com/rust-lang/crates.io-index" 2942 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 2943 | dependencies = [ 2944 | "zerofrom-derive", 2945 | ] 2946 | 2947 | [[package]] 2948 | name = "zerofrom-derive" 2949 | version = "0.1.6" 2950 | source = "registry+https://github.com/rust-lang/crates.io-index" 2951 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 2952 | dependencies = [ 2953 | "proc-macro2", 2954 | "quote", 2955 | "syn", 2956 | "synstructure", 2957 | ] 2958 | 2959 | [[package]] 2960 | name = "zeroize" 2961 | version = "1.8.1" 2962 | source = "registry+https://github.com/rust-lang/crates.io-index" 2963 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 2964 | 2965 | [[package]] 2966 | name = "zerotrie" 2967 | version = "0.2.2" 2968 | source = "registry+https://github.com/rust-lang/crates.io-index" 2969 | checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 2970 | dependencies = [ 2971 | "displaydoc", 2972 | "yoke", 2973 | "zerofrom", 2974 | ] 2975 | 2976 | [[package]] 2977 | name = "zerovec" 2978 | version = "0.11.2" 2979 | source = "registry+https://github.com/rust-lang/crates.io-index" 2980 | checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" 2981 | dependencies = [ 2982 | "yoke", 2983 | "zerofrom", 2984 | "zerovec-derive", 2985 | ] 2986 | 2987 | [[package]] 2988 | name = "zerovec-derive" 2989 | version = "0.11.1" 2990 | source = "registry+https://github.com/rust-lang/crates.io-index" 2991 | checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 2992 | dependencies = [ 2993 | "proc-macro2", 2994 | "quote", 2995 | "syn", 2996 | ] 2997 | 2998 | [[package]] 2999 | name = "zstd" 3000 | version = "0.13.3" 3001 | source = "registry+https://github.com/rust-lang/crates.io-index" 3002 | checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" 3003 | dependencies = [ 3004 | "zstd-safe", 3005 | ] 3006 | 3007 | [[package]] 3008 | name = "zstd-safe" 3009 | version = "7.2.4" 3010 | source = "registry+https://github.com/rust-lang/crates.io-index" 3011 | checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" 3012 | dependencies = [ 3013 | "zstd-sys", 3014 | ] 3015 | 3016 | [[package]] 3017 | name = "zstd-sys" 3018 | version = "2.0.15+zstd.1.5.7" 3019 | source = "registry+https://github.com/rust-lang/crates.io-index" 3020 | checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" 3021 | dependencies = [ 3022 | "cc", 3023 | "pkg-config", 3024 | ] 3025 | 3026 | [[package]] 3027 | name = "zune-core" 3028 | version = "0.4.12" 3029 | source = "registry+https://github.com/rust-lang/crates.io-index" 3030 | checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" 3031 | 3032 | [[package]] 3033 | name = "zune-jpeg" 3034 | version = "0.4.14" 3035 | source = "registry+https://github.com/rust-lang/crates.io-index" 3036 | checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" 3037 | dependencies = [ 3038 | "zune-core", 3039 | ] 3040 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "piped-proxy" 4 | version = "0.1.0" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | # Web Requests & Async Runtime 10 | tokio = { version = "1.37.0", features = ["full"] } 11 | actix-web = "4.5.1" 12 | reqwest = { version = "0.12.9", features = ["stream", "brotli", "gzip", "socks"], default-features = false } 13 | qstring = "0.7.2" 14 | 15 | # Alternate Allocator 16 | mimalloc = { version = "0.1.41", optional = true } 17 | 18 | # Transcoding Images to WebP/AVIF to save bandwidth 19 | image = { version = "0.25.1", features = ["jpeg", "webp", "rayon"], default-features = false, optional = true } 20 | libwebp-sys = { version = "0.12.0", optional = true } 21 | ravif = { version = "0.11.5", optional = true } 22 | rgb = { version = "0.8.37", optional = true } 23 | 24 | once_cell = "1.19.0" 25 | regex = "1.10.4" 26 | blake3 = { version = "1.5.5", optional = true } 27 | bytes = "1.9.0" 28 | futures-util = "0.3.30" 29 | listenfd = "1.0.1" 30 | http = "1.2.0" 31 | 32 | [features] 33 | default = ["webp", "mimalloc", "reqwest-rustls", "qhash"] 34 | 35 | reqwest-rustls = ["reqwest/rustls-tls"] 36 | reqwest-native-tls = ["reqwest/default-tls"] 37 | 38 | avif = ["dep:ravif", "dep:rgb", "dep:image"] 39 | webp = ["dep:libwebp-sys", "dep:image"] 40 | 41 | mimalloc = ["dep:mimalloc"] 42 | 43 | optimized = ["libwebp-sys?/sse41", "libwebp-sys?/avx2", "libwebp-sys?/neon"] 44 | 45 | qhash = ["blake3"] 46 | 47 | [profile.release] 48 | lto = true 49 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:slim as BUILD 2 | 3 | WORKDIR /app/ 4 | 5 | COPY . . 6 | 7 | RUN --mount=type=cache,target=/var/cache/apt \ 8 | apt-get update && \ 9 | apt-get install -y --no-install-recommends \ 10 | nasm && \ 11 | rm -rf /var/lib/apt/lists/* 12 | 13 | RUN --mount=type=cache,target=/usr/local/cargo/registry \ 14 | --mount=type=cache,target=/app/target/ \ 15 | cargo build --release && \ 16 | mv target/release/piped-proxy . 17 | 18 | FROM debian:stable-slim 19 | 20 | RUN --mount=type=cache,target=/var/cache/apt \ 21 | apt-get update && \ 22 | apt-get install -y --no-install-recommends \ 23 | ca-certificates && \ 24 | rm -rf /var/lib/apt/lists/* 25 | 26 | WORKDIR /app/ 27 | 28 | COPY --from=BUILD /app/piped-proxy . 29 | 30 | EXPOSE 8080 31 | 32 | CMD ["/app/piped-proxy"] 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # piped-proxy 2 | 3 | A proxy for Piped written in Rust, meant to superseed [http3-ytproxy](https://github.com/TeamPiped/http3-ytproxy). 4 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base", 5 | "group:recommended" 6 | ], 7 | "ignorePresets": [ 8 | ":prHourlyLimit2" 9 | ], 10 | "platformAutomerge": true, 11 | "packageRules": [ 12 | { 13 | "matchUpdateTypes": ["minor", "patch", "pin", "digest"], 14 | "automerge": true 15 | } 16 | ], 17 | "lockFileMaintenance": { 18 | "enabled": true, 19 | "automerge": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod ump_stream; 2 | mod utils; 3 | 4 | use actix_web::http::StatusCode; 5 | use actix_web::{web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer}; 6 | use listenfd::ListenFd; 7 | use once_cell::sync::Lazy; 8 | use qstring::QString; 9 | use regex::Regex; 10 | use reqwest::{Body, Client, Request, Url}; 11 | use std::error::Error; 12 | use std::io::ErrorKind; 13 | use std::net::TcpListener; 14 | use std::os::unix::net::UnixListener; 15 | use std::str::FromStr; 16 | use std::time::{SystemTime, UNIX_EPOCH}; 17 | use std::{env, io}; 18 | 19 | #[cfg(not(any(feature = "reqwest-native-tls", feature = "reqwest-rustls")))] 20 | compile_error!("feature \"reqwest-native-tls\" or \"reqwest-rustls\" must be set for proxy to have TLS support"); 21 | 22 | use futures_util::TryStreamExt; 23 | use http::{HeaderName, Method}; 24 | use reqwest::header::HeaderValue; 25 | #[cfg(any(feature = "webp", feature = "avif", feature = "qhash"))] 26 | use tokio::task::spawn_blocking; 27 | use ump_stream::UmpTransformStream; 28 | 29 | #[cfg(feature = "mimalloc")] 30 | #[global_allocator] 31 | static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; 32 | 33 | fn try_get_fd_listeners() -> (Option, Option) { 34 | let mut fd = ListenFd::from_env(); 35 | 36 | let unix_listener = env::var("FD_UNIX").ok().map(|fd_unix| { 37 | let fd_pos = fd_unix.parse().expect("FD_UNIX is not a number"); 38 | println!("Trying to take Unix socket at position {}", fd_pos); 39 | fd.take_unix_listener(fd_pos) 40 | .expect(format!("fd {} is not a Unix socket", fd_pos).as_str()) 41 | .expect(format!("fd {} has already been used", fd_pos).as_str()) 42 | }); 43 | 44 | let tcp_listener = env::var("FD_TCP").ok().map(|fd_tcp| { 45 | let fd_pos = fd_tcp.parse().expect("FD_TCP is not a number"); 46 | println!("Trying to take TCP listener at position {}", fd_pos); 47 | fd.take_tcp_listener(fd_pos) 48 | .expect(format!("fd {} is not a TCP listener", fd_pos).as_str()) 49 | .expect(format!("fd {} has already been used", fd_pos).as_str()) 50 | }); 51 | 52 | (unix_listener, tcp_listener) 53 | } 54 | 55 | #[actix_web::main] 56 | async fn main() -> std::io::Result<()> { 57 | println!("Running server!"); 58 | 59 | let mut server = HttpServer::new(|| { 60 | // match all requests 61 | App::new().default_service(web::to(index)) 62 | }); 63 | 64 | let fd_listeners = try_get_fd_listeners(); 65 | 66 | if let Some(unix_listener) = fd_listeners.0 { 67 | server = server 68 | .listen_uds(unix_listener) 69 | .expect("Error while trying to listen on Unix socket passed by fd"); 70 | println!("Listening on Unix socket passed by fd."); 71 | } 72 | 73 | if let Some(tcp_listener) = fd_listeners.1 { 74 | server = server 75 | .listen(tcp_listener) 76 | .expect("Error while trying to listen on TCP listener passed by fd"); 77 | println!("Listening on TCP listener passed by fd."); 78 | } 79 | 80 | // Only bind manually if there is not already a listener 81 | if server.addrs().is_empty() { 82 | // get socket/port from env 83 | // backwards compat when only UDS is set 84 | server = if utils::get_env_bool("UDS") { 85 | let socket_path = 86 | env::var("BIND_UNIX").unwrap_or_else(|_| "./socket/actix.sock".to_string()); 87 | server.bind_uds(socket_path)? 88 | } else { 89 | let bind = env::var("BIND").unwrap_or_else(|_| "0.0.0.0:8080".to_string()); 90 | server.bind(bind)? 91 | }; 92 | } 93 | 94 | server.run().await 95 | } 96 | 97 | static RE_DOMAIN: Lazy = 98 | Lazy::new(|| Regex::new(r"^(?:[a-z\d.-]*\.)?([a-z\d-]*\.[a-z\d-]*)$").unwrap()); 99 | static RE_MANIFEST: Lazy = Lazy::new(|| Regex::new("(?m)URI=\"([^\"]+)\"").unwrap()); 100 | static RE_DASH_MANIFEST: Lazy = 101 | Lazy::new(|| Regex::new("BaseURL>(https://[^<]+) = Lazy::new(|| { 104 | let builder = Client::builder() 105 | .user_agent("Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0"); 106 | 107 | let proxy = if let Ok(proxy) = env::var("PROXY") { 108 | reqwest::Proxy::all(proxy).ok() 109 | } else { 110 | None 111 | }; 112 | 113 | let builder = if let Some(proxy) = proxy { 114 | // proxy basic auth 115 | if let Ok(proxy_auth_user) = env::var("PROXY_USER") { 116 | let proxy_auth_pass = env::var("PROXY_PASS").unwrap_or_default(); 117 | builder.proxy(proxy.basic_auth(&proxy_auth_user, &proxy_auth_pass)) 118 | } else { 119 | builder.proxy(proxy) 120 | } 121 | } else { 122 | builder 123 | }; 124 | 125 | if utils::get_env_bool("IPV4_ONLY") { 126 | builder.local_address("0.0.0.0".parse().ok()) 127 | } else { 128 | builder 129 | } 130 | .build() 131 | .unwrap() 132 | }); 133 | 134 | const ANDROID_USER_AGENT: &str = "com.google.android.youtube/1537338816 (Linux; U; Android 13; en_US; ; Build/TQ2A.230505.002; Cronet/113.0.5672.24)"; 135 | const ALLOWED_DOMAINS: [&str; 8] = [ 136 | "youtube.com", 137 | "googlevideo.com", 138 | "ytimg.com", 139 | "ggpht.com", 140 | "googleusercontent.com", 141 | "lbryplayer.xyz", 142 | "odycdn.com", 143 | "ajay.app", 144 | ]; 145 | 146 | fn add_headers(response: &mut HttpResponseBuilder) { 147 | response 148 | .append_header(("Access-Control-Allow-Origin", "*")) 149 | .append_header(("Access-Control-Allow-Headers", "*")) 150 | .append_header(("Access-Control-Allow-Methods", "*")) 151 | .append_header(("Access-Control-Max-Age", "1728000")); 152 | } 153 | 154 | fn is_header_allowed(header: &str) -> bool { 155 | if header.starts_with("access-control") { 156 | return false; 157 | } 158 | 159 | !matches!( 160 | header, 161 | "host" 162 | | "content-length" 163 | | "set-cookie" 164 | | "alt-svc" 165 | | "accept-ch" 166 | | "report-to" 167 | | "strict-transport-security" 168 | | "user-agent" 169 | | "range" 170 | | "transfer-encoding" 171 | | "x-real-ip" 172 | | "origin" 173 | | "referer" 174 | // the 'x-title' header contains non-ascii characters which is not allowed on some HTTP clients 175 | | "x-title" 176 | ) 177 | } 178 | 179 | async fn index(req: HttpRequest) -> Result> { 180 | if req.method() == actix_web::http::Method::OPTIONS { 181 | let mut response = HttpResponse::Ok(); 182 | add_headers(&mut response); 183 | return Ok(response.finish()); 184 | } else if req.method() != actix_web::http::Method::GET 185 | && req.method() != actix_web::http::Method::HEAD 186 | { 187 | let mut response = HttpResponse::MethodNotAllowed(); 188 | add_headers(&mut response); 189 | return Ok(response.finish()); 190 | } 191 | 192 | // parse query string 193 | let mut query = QString::from(req.query_string()); 194 | 195 | #[cfg(feature = "qhash")] 196 | { 197 | use std::collections::BTreeSet; 198 | 199 | let secret = env::var("HASH_SECRET"); 200 | if let Ok(secret) = secret { 201 | let Some(qhash) = query.get("qhash") else { 202 | return Err("No qhash provided".into()); 203 | }; 204 | 205 | if qhash.len() != 8 { 206 | return Err("Invalid qhash provided".into()); 207 | } 208 | 209 | let path = req.path().as_bytes().to_owned(); 210 | 211 | // Store sorted key-value pairs 212 | let mut set = BTreeSet::new(); 213 | { 214 | let pairs = query.to_pairs(); 215 | for (key, value) in &pairs { 216 | if matches!(*key, "qhash" | "range" | "rewrite") { 217 | continue; 218 | } 219 | set.insert((key.as_bytes().to_owned(), value.as_bytes().to_owned())); 220 | } 221 | } 222 | 223 | let hash = spawn_blocking(move || { 224 | let mut hasher = blake3::Hasher::new(); 225 | 226 | for (key, value) in set { 227 | hasher.update(&key); 228 | hasher.update(&value); 229 | } 230 | 231 | let range_marker = b"/range/"; 232 | 233 | // Find the slice before "/range/" 234 | if let Some(position) = path 235 | .windows(range_marker.len()) 236 | .position(|window| window == range_marker) 237 | { 238 | // Update the hasher with the part of the path before "/range/" 239 | // We add +1 to include the "/" in the hash 240 | // This is done for DASH streams for the manifests provided by YouTube 241 | hasher.update(&path[..(position + 1)]); 242 | } else { 243 | hasher.update(&path); 244 | } 245 | 246 | hasher.update(secret.as_bytes()); 247 | 248 | let hash = hasher.finalize().to_hex(); 249 | 250 | hash[..8].to_owned() 251 | }) 252 | .await 253 | .unwrap(); 254 | 255 | if hash != qhash { 256 | return Err("Invalid qhash provided".into()); 257 | } 258 | } 259 | } 260 | 261 | let Some(host) = query.get("host").map(|s| s.to_string()) else { 262 | return Err("No host provided".into()); 263 | }; 264 | 265 | #[cfg(any(feature = "webp", feature = "avif"))] 266 | let disallow_image_transcoding = utils::get_env_bool("DISALLOW_IMAGE_TRANSCODING"); 267 | 268 | let rewrite = query.get("rewrite") != Some("false"); 269 | 270 | #[cfg(feature = "avif")] 271 | let avif = query.get("avif") == Some("true"); 272 | 273 | let Some(domain) = RE_DOMAIN 274 | .captures(host.as_str()) 275 | .map(|domain| domain.get(1).unwrap().as_str()) 276 | else { 277 | return Err("Invalid host provided".into()); 278 | }; 279 | 280 | if !ALLOWED_DOMAINS.contains(&domain) { 281 | return Err("Domain not allowed".into()); 282 | } 283 | 284 | let video_playback = req.path().eq("/videoplayback"); 285 | 286 | if video_playback { 287 | if let Some(expiry) = query.get("expire") { 288 | let expiry = expiry.parse::()?; 289 | let now = SystemTime::now(); 290 | let now = now.duration_since(UNIX_EPOCH) 291 | .expect("Time went backwards") 292 | .as_secs() as i64; 293 | if now > expiry { 294 | return Err("Expire time in past".into()); 295 | } 296 | } 297 | } 298 | 299 | let is_android = video_playback && query.get("c").unwrap_or("").eq("ANDROID"); 300 | let is_web = video_playback && query.get("c").unwrap_or("").eq("WEB"); 301 | 302 | let is_ump = video_playback && query.get("ump").is_some(); 303 | 304 | let mime_type = query.get("mime").map(|s| s.to_string()); 305 | 306 | let clen = query 307 | .get("clen") 308 | .map(|s| s.to_string().parse::().unwrap()); 309 | 310 | if video_playback && !query.has("range") { 311 | if let Some(range) = req.headers().get("range") { 312 | let range = range.to_str().unwrap(); 313 | let range = range.replace("bytes=", ""); 314 | let range = range.split('-').collect::>(); 315 | let start = range[0].parse::().unwrap(); 316 | let end = match range[1].parse::() { 317 | Ok(end) => end, 318 | Err(_) => { 319 | if let Some(clen) = clen { 320 | clen - 1 321 | } else { 322 | 0 323 | } 324 | } 325 | }; 326 | if end != 0 { 327 | let range = format!("{}-{}", start, end); 328 | query.add_pair(("range", range)); 329 | } 330 | } else if let Some(clen) = clen { 331 | let range = format!("0-{}", clen - 1); 332 | query.add_pair(("range", range)); 333 | } 334 | } 335 | 336 | let range = query.get("range").map(|s| s.to_string()); 337 | 338 | let qs = { 339 | let collected = query 340 | .into_pairs() 341 | .into_iter() 342 | .filter(|(key, _)| !matches!(key.as_str(), "host" | "rewrite" | "qhash")) 343 | .collect::>(); 344 | QString::new(collected) 345 | }; 346 | 347 | let mut url = Url::parse(&format!("https://{}{}", host, req.path()))?; 348 | url.set_query(Some(qs.to_string().as_str())); 349 | 350 | let method = { 351 | if is_web && video_playback { 352 | Method::POST 353 | } else { 354 | Method::from_str(req.method().as_str())? 355 | } 356 | }; 357 | 358 | let mut request = Request::new(method, url); 359 | 360 | if is_web && video_playback { 361 | request.body_mut().replace(Body::from("x\0")); 362 | } 363 | 364 | let request_headers = request.headers_mut(); 365 | 366 | for (key, value) in req.headers() { 367 | let key = key.as_str(); 368 | if is_header_allowed(key) { 369 | request_headers.insert( 370 | HeaderName::from_str(key)?, 371 | HeaderValue::from_bytes(value.as_bytes())?, 372 | ); 373 | } 374 | } 375 | 376 | if is_android { 377 | request_headers.insert("User-Agent", ANDROID_USER_AGENT.parse()?); 378 | } 379 | 380 | let resp = CLIENT.execute(request).await?; 381 | 382 | let mut response = HttpResponse::build(StatusCode::from_u16(resp.status().as_u16())?); 383 | 384 | add_headers(&mut response); 385 | 386 | for (key, value) in resp.headers() { 387 | if is_header_allowed(key.as_str()) { 388 | response.append_header((key.as_str(), value.as_bytes())); 389 | } 390 | } 391 | 392 | if rewrite { 393 | if let Some(content_type) = resp.headers().get("content-type") { 394 | #[cfg(feature = "avif")] 395 | if !disallow_image_transcoding 396 | && (content_type == "image/webp" || content_type == "image/jpeg" && avif) 397 | { 398 | let resp_bytes = resp.bytes().await.unwrap(); 399 | let (body, content_type) = spawn_blocking(|| { 400 | use ravif::{Encoder, Img}; 401 | use rgb::FromSlice; 402 | 403 | let image = image::load_from_memory(&resp_bytes).unwrap(); 404 | 405 | let width = image.width() as usize; 406 | let height = image.height() as usize; 407 | 408 | let buf = image.into_rgb8(); 409 | let buf = buf.as_raw().as_rgb(); 410 | 411 | let buffer = Img::new(buf, width, height); 412 | 413 | let res = Encoder::new() 414 | .with_quality(80f32) 415 | .with_speed(7) 416 | .encode_rgb(buffer); 417 | 418 | if let Ok(res) = res { 419 | (res.avif_file.to_vec(), "image/avif") 420 | } else { 421 | (resp_bytes.into(), "image/jpeg") 422 | } 423 | }) 424 | .await 425 | .unwrap(); 426 | response.content_type(content_type); 427 | return Ok(response.body(body)); 428 | } 429 | 430 | #[cfg(feature = "webp")] 431 | if !disallow_image_transcoding && content_type == "image/jpeg" { 432 | let resp_bytes = resp.bytes().await.unwrap(); 433 | let (body, content_type) = spawn_blocking(|| { 434 | use libwebp_sys::{WebPEncodeRGB, WebPFree}; 435 | 436 | let image = image::load_from_memory(&resp_bytes).unwrap(); 437 | let width = image.width(); 438 | let height = image.height(); 439 | 440 | let quality = 85; 441 | 442 | let data = image.as_rgb8().unwrap().as_raw(); 443 | 444 | let bytes: Vec = unsafe { 445 | let mut out_buf = std::ptr::null_mut(); 446 | let stride = width as i32 * 3; 447 | let len: usize = WebPEncodeRGB( 448 | data.as_ptr(), 449 | width as i32, 450 | height as i32, 451 | stride, 452 | quality as f32, 453 | &mut out_buf, 454 | ); 455 | let vec = std::slice::from_raw_parts(out_buf, len).into(); 456 | WebPFree(out_buf as *mut _); 457 | vec 458 | }; 459 | 460 | if bytes.len() < resp_bytes.len() { 461 | (bytes, "image/webp") 462 | } else { 463 | (resp_bytes.into(), "image/jpeg") 464 | } 465 | }) 466 | .await 467 | .unwrap(); 468 | response.content_type(content_type); 469 | return Ok(response.body(body)); 470 | } 471 | 472 | if content_type == "application/x-mpegurl" 473 | || content_type == "application/vnd.apple.mpegurl" 474 | { 475 | let resp_str = resp.text().await.unwrap(); 476 | 477 | let modified = resp_str 478 | .lines() 479 | .map(|line| { 480 | let captures = RE_MANIFEST.captures(line); 481 | if let Some(captures) = captures { 482 | let url = captures.get(1).unwrap().as_str(); 483 | if url.starts_with("https://") { 484 | return line.replace( 485 | url, 486 | utils::localize_url(url, host.as_str()).as_str(), 487 | ); 488 | } 489 | } 490 | utils::localize_url(line, host.as_str()) 491 | }) 492 | .collect::>() 493 | .join("\n"); 494 | 495 | return Ok(response.body(modified)); 496 | } 497 | if content_type == "video/vnd.mpeg.dash.mpd" || content_type == "application/dash+xml" { 498 | let resp_str = resp.text().await.unwrap(); 499 | let mut new_resp = resp_str.clone(); 500 | let captures = RE_DASH_MANIFEST.captures_iter(&resp_str); 501 | for capture in captures { 502 | let url = capture.get(1).unwrap().as_str(); 503 | let new_url = utils::localize_url(url, host.as_str()); 504 | let new_url = utils::escape_xml(new_url.as_str()); 505 | new_resp = new_resp.replace(url, new_url.as_ref()); 506 | } 507 | return Ok(response.body(new_resp)); 508 | } 509 | } 510 | } 511 | 512 | if let Some(content_length) = resp.headers().get("content-length") { 513 | response.no_chunking(content_length.to_str().unwrap().parse::().unwrap()); 514 | } 515 | 516 | if is_ump && resp.status().is_success() { 517 | if let Some(mime_type) = mime_type { 518 | response.content_type(mime_type); 519 | } 520 | if req.headers().contains_key("range") { 521 | // check if it's not the whole stream 522 | if let Some(ref range) = range { 523 | if let Some(clen) = clen { 524 | if range != &format!("0-{}", clen - 1) { 525 | response.status(StatusCode::PARTIAL_CONTENT); 526 | } 527 | } 528 | } 529 | } 530 | let resp = resp.bytes_stream(); 531 | let resp = resp.map_err(|e| io::Error::new(ErrorKind::Other, e)); 532 | let transformed_stream = UmpTransformStream::new(resp); 533 | // print errors 534 | let transformed_stream = transformed_stream.map_err(|e| { 535 | eprintln!("UMP Transforming Error: {}", e); 536 | e 537 | }); 538 | 539 | // calculate content length from clen and range 540 | if let Some(clen) = clen { 541 | let length = if let Some(ref range) = range { 542 | let range = range.replace("bytes=", ""); 543 | let range = range.split('-').collect::>(); 544 | let start = range[0].parse::().unwrap(); 545 | let end = range[1].parse::().unwrap_or(clen - 1); 546 | end - start + 1 547 | } else { 548 | clen 549 | }; 550 | response.no_chunking(length); 551 | } 552 | 553 | return Ok(response.streaming(transformed_stream)); 554 | } 555 | 556 | // Stream response 557 | Ok(response.streaming(resp.bytes_stream())) 558 | } 559 | -------------------------------------------------------------------------------- /src/ump_stream.rs: -------------------------------------------------------------------------------- 1 | use crate::utils; 2 | use bytes::{Bytes, BytesMut}; 3 | use futures_util::Stream; 4 | use std::io; 5 | use std::io::ErrorKind; 6 | use std::pin::Pin; 7 | use std::task::{Context, Poll}; 8 | 9 | fn read_variable_integer(buf: &[u8], offset: usize) -> io::Result<(i32, usize)> { 10 | let mut pos = offset; 11 | let prefix = utils::read_buf(buf, &mut pos); 12 | let mut size = 0; 13 | for shift in 1..=5 { 14 | if prefix & (128 >> (shift - 1)) == 0 { 15 | size = shift; 16 | break; 17 | } 18 | } 19 | if !(1..=5).contains(&size) { 20 | return Err(io::Error::new( 21 | ErrorKind::InvalidData, 22 | format!("Invalid integer size {} at position {}", size, offset), 23 | )); 24 | } 25 | 26 | match size { 27 | 1 => Ok((prefix as i32, size)), 28 | 2 => { 29 | let value = ((utils::read_buf(buf, &mut pos) as i32) << 6) | (prefix as i32 & 0b111111); 30 | Ok((value, size)) 31 | } 32 | 3 => { 33 | let value = (((utils::read_buf(buf, &mut pos) as i32) 34 | | ((utils::read_buf(buf, &mut pos) as i32) << 8)) 35 | << 5) 36 | | (prefix as i32 & 0b11111); 37 | Ok((value, size)) 38 | } 39 | 4 => { 40 | let value = (((utils::read_buf(buf, &mut pos) as i32) 41 | | ((utils::read_buf(buf, &mut pos) as i32) << 8) 42 | | ((utils::read_buf(buf, &mut pos) as i32) << 16)) 43 | << 4) 44 | | (prefix as i32 & 0b1111); 45 | Ok((value, size)) 46 | } 47 | _ => { 48 | let value = (utils::read_buf(buf, &mut pos) as i32) 49 | | ((utils::read_buf(buf, &mut pos) as i32) << 8) 50 | | ((utils::read_buf(buf, &mut pos) as i32) << 16) 51 | | ((utils::read_buf(buf, &mut pos) as i32) << 24); 52 | Ok((value, size)) 53 | } 54 | } 55 | } 56 | 57 | pub struct UmpTransformStream 58 | where 59 | S: Stream> + Unpin, 60 | { 61 | inner: S, 62 | buffer: BytesMut, 63 | found_stream: bool, 64 | remaining: usize, 65 | } 66 | 67 | impl UmpTransformStream 68 | where 69 | S: Stream> + Unpin, 70 | { 71 | pub fn new(stream: S) -> Self { 72 | UmpTransformStream { 73 | inner: stream, 74 | buffer: BytesMut::new(), 75 | found_stream: false, 76 | remaining: 0, 77 | } 78 | } 79 | } 80 | 81 | impl Stream for UmpTransformStream 82 | where 83 | S: Stream> + Unpin, 84 | { 85 | type Item = Result; 86 | 87 | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 88 | let this = self.get_mut(); 89 | 90 | while let Poll::Ready(item) = Pin::new(&mut this.inner).poll_next(cx) { 91 | match item { 92 | Some(Ok(bytes)) => { 93 | if this.found_stream { 94 | if this.remaining > 0 { 95 | let len = std::cmp::min(this.remaining, bytes.len()); 96 | this.remaining -= len; 97 | if this.remaining == 0 { 98 | this.buffer.clear(); 99 | this.buffer.extend_from_slice(&bytes[len..]); 100 | this.found_stream = false; 101 | } 102 | return Poll::Ready(Some(Ok(bytes.slice(0..len)))); 103 | } else { 104 | this.found_stream = false; 105 | this.buffer.clear(); 106 | this.buffer.extend_from_slice(&bytes); 107 | }; 108 | } else { 109 | this.buffer.extend_from_slice(&bytes); 110 | } 111 | } 112 | Some(Err(e)) => return Poll::Ready(Some(Err(e))), 113 | None => { 114 | return Poll::Ready(None); 115 | } 116 | } 117 | } 118 | 119 | if !this.found_stream && !this.buffer.is_empty() { 120 | let (segment_type, s1) = match read_variable_integer(&this.buffer, 0) { 121 | Ok(result) => result, 122 | Err(_) => return Poll::Pending, 123 | }; 124 | let (segment_length, s2) = match read_variable_integer(&this.buffer, s1) { 125 | Ok(result) => result, 126 | Err(_) => return Poll::Pending, 127 | }; 128 | if segment_type != 21 { 129 | // Not the stream 130 | if this.buffer.len() > s1 + s2 + segment_length as usize { 131 | let _ = this.buffer.split_to(s1 + s2 + segment_length as usize); 132 | } 133 | } else { 134 | this.remaining = segment_length as usize - 1; 135 | 136 | let _ = this.buffer.split_to(s1 + s2 + 1); 137 | 138 | if this.buffer.len() > segment_length as usize { 139 | let len = std::cmp::min(this.remaining, this.buffer.len()); 140 | this.remaining -= len; 141 | 142 | return Poll::Ready(Some(Ok(this.buffer.split_to(len).into()))); 143 | } else { 144 | this.remaining -= this.buffer.len(); 145 | this.found_stream = true; 146 | 147 | return Poll::Ready(Some(Ok(this.buffer.to_vec().into()))); 148 | } 149 | } 150 | } 151 | 152 | Poll::Pending 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use qstring::QString; 2 | use reqwest::Url; 3 | use std::borrow::Cow; 4 | use std::collections::BTreeMap; 5 | use std::env; 6 | 7 | pub fn read_buf(buf: &[u8], pos: &mut usize) -> u8 { 8 | let byte = buf[*pos]; 9 | *pos += 1; 10 | byte 11 | } 12 | 13 | fn finalize_url(path: &str, query: BTreeMap) -> String { 14 | #[cfg(feature = "qhash")] 15 | { 16 | use std::collections::BTreeSet; 17 | 18 | let qhash = { 19 | let secret = env::var("HASH_SECRET"); 20 | if let Ok(secret) = secret { 21 | let set = query 22 | .iter() 23 | .filter(|(key, _)| !matches!(key.as_str(), "qhash" | "range" | "rewrite")) 24 | .map(|(key, value)| (key.as_bytes().to_owned(), value.as_bytes().to_owned())) 25 | .collect::>(); 26 | 27 | let mut hasher = blake3::Hasher::new(); 28 | 29 | for (key, value) in set { 30 | hasher.update(&key); 31 | hasher.update(&value); 32 | } 33 | 34 | hasher.update(path.as_bytes()); 35 | 36 | hasher.update(secret.as_bytes()); 37 | 38 | let hash = hasher.finalize().to_hex(); 39 | 40 | Some(hash[..8].to_owned()) 41 | } else { 42 | None 43 | } 44 | }; 45 | 46 | if let Some(qhash) = qhash { 47 | let mut query = QString::new(query.into_iter().collect::>()); 48 | query.add_pair(("qhash", qhash)); 49 | return format!("{}?{}", path, query); 50 | } 51 | } 52 | 53 | let query = QString::new(query.into_iter().collect::>()); 54 | format!("{}?{}", path, query) 55 | } 56 | 57 | pub fn localize_url(url: &str, host: &str) -> String { 58 | if url.starts_with("https://") { 59 | let url = Url::parse(url).unwrap(); 60 | let host = url.host().unwrap().to_string(); 61 | 62 | let mut query = url.query_pairs().into_owned().collect::>(); 63 | 64 | query.insert("host".to_string(), host.clone()); 65 | 66 | return finalize_url(url.path(), query); 67 | } else if url.ends_with(".m3u8") || url.ends_with(".ts") { 68 | let mut query = BTreeMap::new(); 69 | query.insert("host".to_string(), host.to_string()); 70 | 71 | return finalize_url(url, query); 72 | } 73 | 74 | url.to_string() 75 | } 76 | 77 | pub fn escape_xml(raw: &str) -> Cow<'_, str> { 78 | if !raw.contains(&['<', '>', '&', '\'', '"'][..]) { 79 | // If there are no characters to escape, return the original string. 80 | Cow::Borrowed(raw) 81 | } else { 82 | // If there are characters to escape, build a new string with the replacements. 83 | let mut escaped = String::with_capacity(raw.len()); 84 | for c in raw.chars() { 85 | match c { 86 | '<' => escaped.push_str("<"), 87 | '>' => escaped.push_str(">"), 88 | '&' => escaped.push_str("&"), 89 | '\'' => escaped.push_str("'"), 90 | '"' => escaped.push_str("""), 91 | _ => escaped.push(c), 92 | } 93 | } 94 | Cow::Owned(escaped) 95 | } 96 | } 97 | 98 | pub fn get_env_bool(key: &str) -> bool { 99 | match env::var(key) { 100 | Ok(val) => val.to_lowercase() == "true" || val == "1", 101 | Err(_) => false, 102 | } 103 | } 104 | --------------------------------------------------------------------------------