├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── package.json ├── src ├── lib.rs └── utils.rs └── wrangler.toml /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /node_modules 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "adler32" 22 | version = "1.2.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" 25 | 26 | [[package]] 27 | name = "aho-corasick" 28 | version = "1.1.3" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 31 | dependencies = [ 32 | "memchr", 33 | ] 34 | 35 | [[package]] 36 | name = "async-trait" 37 | version = "0.1.80" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" 40 | dependencies = [ 41 | "proc-macro2 1.0.79", 42 | "quote 1.0.36", 43 | "syn 2.0.58", 44 | ] 45 | 46 | [[package]] 47 | name = "autocfg" 48 | version = "0.1.8" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" 51 | dependencies = [ 52 | "autocfg 1.2.0", 53 | ] 54 | 55 | [[package]] 56 | name = "autocfg" 57 | version = "1.2.0" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" 60 | 61 | [[package]] 62 | name = "backtrace" 63 | version = "0.3.71" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 66 | dependencies = [ 67 | "addr2line", 68 | "cc", 69 | "cfg-if", 70 | "libc", 71 | "miniz_oxide 0.7.2", 72 | "object", 73 | "rustc-demangle", 74 | ] 75 | 76 | [[package]] 77 | name = "bitflags" 78 | version = "1.3.2" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 81 | 82 | [[package]] 83 | name = "bumpalo" 84 | version = "3.16.0" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 87 | 88 | [[package]] 89 | name = "bytemuck" 90 | version = "1.15.0" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" 93 | 94 | [[package]] 95 | name = "byteorder" 96 | version = "1.5.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 99 | 100 | [[package]] 101 | name = "bytes" 102 | version = "1.6.0" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 105 | 106 | [[package]] 107 | name = "cc" 108 | version = "1.0.94" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" 111 | 112 | [[package]] 113 | name = "cfg-if" 114 | version = "1.0.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 117 | 118 | [[package]] 119 | name = "chrono" 120 | version = "0.4.37" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" 123 | dependencies = [ 124 | "js-sys", 125 | "num-traits", 126 | "wasm-bindgen", 127 | ] 128 | 129 | [[package]] 130 | name = "chrono-tz" 131 | version = "0.8.6" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" 134 | dependencies = [ 135 | "chrono", 136 | "chrono-tz-build", 137 | "phf 0.11.2", 138 | ] 139 | 140 | [[package]] 141 | name = "chrono-tz-build" 142 | version = "0.2.1" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" 145 | dependencies = [ 146 | "parse-zoneinfo", 147 | "phf 0.11.2", 148 | "phf_codegen 0.11.2", 149 | ] 150 | 151 | [[package]] 152 | name = "cloudabi" 153 | version = "0.0.3" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 156 | dependencies = [ 157 | "bitflags", 158 | ] 159 | 160 | [[package]] 161 | name = "color_quant" 162 | version = "1.1.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 165 | 166 | [[package]] 167 | name = "crc32fast" 168 | version = "1.4.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" 171 | dependencies = [ 172 | "cfg-if", 173 | ] 174 | 175 | [[package]] 176 | name = "crossbeam-deque" 177 | version = "0.8.5" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 180 | dependencies = [ 181 | "crossbeam-epoch", 182 | "crossbeam-utils", 183 | ] 184 | 185 | [[package]] 186 | name = "crossbeam-epoch" 187 | version = "0.9.18" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 190 | dependencies = [ 191 | "crossbeam-utils", 192 | ] 193 | 194 | [[package]] 195 | name = "crossbeam-utils" 196 | version = "0.8.19" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" 199 | 200 | [[package]] 201 | name = "deflate" 202 | version = "0.8.6" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" 205 | dependencies = [ 206 | "adler32", 207 | "byteorder", 208 | ] 209 | 210 | [[package]] 211 | name = "either" 212 | version = "1.11.0" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" 215 | 216 | [[package]] 217 | name = "favicon-rustler" 218 | version = "0.1.0" 219 | dependencies = [ 220 | "image", 221 | "log", 222 | "serde_json", 223 | "soup", 224 | "url", 225 | "wasm-bindgen", 226 | "worker", 227 | ] 228 | 229 | [[package]] 230 | name = "fnv" 231 | version = "1.0.7" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 234 | 235 | [[package]] 236 | name = "form_urlencoded" 237 | version = "1.2.1" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 240 | dependencies = [ 241 | "percent-encoding", 242 | ] 243 | 244 | [[package]] 245 | name = "fuchsia-cprng" 246 | version = "0.1.1" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 249 | 250 | [[package]] 251 | name = "futf" 252 | version = "0.1.5" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" 255 | dependencies = [ 256 | "mac", 257 | "new_debug_unreachable", 258 | ] 259 | 260 | [[package]] 261 | name = "futures-channel" 262 | version = "0.3.30" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 265 | dependencies = [ 266 | "futures-core", 267 | ] 268 | 269 | [[package]] 270 | name = "futures-core" 271 | version = "0.3.30" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 274 | 275 | [[package]] 276 | name = "futures-io" 277 | version = "0.3.30" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 280 | 281 | [[package]] 282 | name = "futures-macro" 283 | version = "0.3.30" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 286 | dependencies = [ 287 | "proc-macro2 1.0.79", 288 | "quote 1.0.36", 289 | "syn 2.0.58", 290 | ] 291 | 292 | [[package]] 293 | name = "futures-sink" 294 | version = "0.3.30" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 297 | 298 | [[package]] 299 | name = "futures-task" 300 | version = "0.3.30" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 303 | 304 | [[package]] 305 | name = "futures-util" 306 | version = "0.3.30" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 309 | dependencies = [ 310 | "futures-core", 311 | "futures-io", 312 | "futures-macro", 313 | "futures-sink", 314 | "futures-task", 315 | "memchr", 316 | "pin-project-lite", 317 | "pin-utils", 318 | "slab", 319 | ] 320 | 321 | [[package]] 322 | name = "gif" 323 | version = "0.11.4" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" 326 | dependencies = [ 327 | "color_quant", 328 | "weezl", 329 | ] 330 | 331 | [[package]] 332 | name = "gimli" 333 | version = "0.28.1" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 336 | 337 | [[package]] 338 | name = "html5ever" 339 | version = "0.22.5" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "c213fa6a618dc1da552f54f85cba74b05d8e883c92ec4e89067736938084c26e" 342 | dependencies = [ 343 | "log", 344 | "mac", 345 | "markup5ever", 346 | "proc-macro2 0.4.30", 347 | "quote 0.6.13", 348 | "syn 0.15.44", 349 | ] 350 | 351 | [[package]] 352 | name = "http" 353 | version = "0.2.12" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 356 | dependencies = [ 357 | "bytes", 358 | "fnv", 359 | "itoa", 360 | ] 361 | 362 | [[package]] 363 | name = "idna" 364 | version = "0.5.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 367 | dependencies = [ 368 | "unicode-bidi", 369 | "unicode-normalization", 370 | ] 371 | 372 | [[package]] 373 | name = "image" 374 | version = "0.23.14" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" 377 | dependencies = [ 378 | "bytemuck", 379 | "byteorder", 380 | "color_quant", 381 | "gif", 382 | "jpeg-decoder", 383 | "num-iter", 384 | "num-rational", 385 | "num-traits", 386 | "png", 387 | "scoped_threadpool", 388 | "tiff", 389 | ] 390 | 391 | [[package]] 392 | name = "itoa" 393 | version = "1.0.11" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 396 | 397 | [[package]] 398 | name = "jpeg-decoder" 399 | version = "0.1.22" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" 402 | dependencies = [ 403 | "rayon", 404 | ] 405 | 406 | [[package]] 407 | name = "js-sys" 408 | version = "0.3.63" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" 411 | dependencies = [ 412 | "wasm-bindgen", 413 | ] 414 | 415 | [[package]] 416 | name = "lazy_static" 417 | version = "1.4.0" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 420 | 421 | [[package]] 422 | name = "libc" 423 | version = "0.2.153" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 426 | 427 | [[package]] 428 | name = "log" 429 | version = "0.4.21" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 432 | 433 | [[package]] 434 | name = "mac" 435 | version = "0.1.1" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" 438 | 439 | [[package]] 440 | name = "markup5ever" 441 | version = "0.7.5" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "897636f9850c3eef4905a5540683ed53dc9393860f0846cab2c2ddf9939862ff" 444 | dependencies = [ 445 | "phf 0.7.24", 446 | "phf_codegen 0.7.24", 447 | "serde", 448 | "serde_derive", 449 | "serde_json", 450 | "string_cache", 451 | "string_cache_codegen", 452 | "tendril", 453 | ] 454 | 455 | [[package]] 456 | name = "matchit" 457 | version = "0.4.6" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "9376a4f0340565ad675d11fc1419227faf5f60cd7ac9cb2e7185a471f30af833" 460 | 461 | [[package]] 462 | name = "memchr" 463 | version = "2.7.2" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 466 | 467 | [[package]] 468 | name = "miniz_oxide" 469 | version = "0.3.7" 470 | source = "registry+https://github.com/rust-lang/crates.io-index" 471 | checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" 472 | dependencies = [ 473 | "adler32", 474 | ] 475 | 476 | [[package]] 477 | name = "miniz_oxide" 478 | version = "0.4.4" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 481 | dependencies = [ 482 | "adler", 483 | "autocfg 1.2.0", 484 | ] 485 | 486 | [[package]] 487 | name = "miniz_oxide" 488 | version = "0.7.2" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 491 | dependencies = [ 492 | "adler", 493 | ] 494 | 495 | [[package]] 496 | name = "new_debug_unreachable" 497 | version = "1.0.6" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 500 | 501 | [[package]] 502 | name = "num-integer" 503 | version = "0.1.46" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 506 | dependencies = [ 507 | "num-traits", 508 | ] 509 | 510 | [[package]] 511 | name = "num-iter" 512 | version = "0.1.44" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" 515 | dependencies = [ 516 | "autocfg 1.2.0", 517 | "num-integer", 518 | "num-traits", 519 | ] 520 | 521 | [[package]] 522 | name = "num-rational" 523 | version = "0.3.2" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 526 | dependencies = [ 527 | "autocfg 1.2.0", 528 | "num-integer", 529 | "num-traits", 530 | ] 531 | 532 | [[package]] 533 | name = "num-traits" 534 | version = "0.2.18" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" 537 | dependencies = [ 538 | "autocfg 1.2.0", 539 | ] 540 | 541 | [[package]] 542 | name = "object" 543 | version = "0.32.2" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 546 | dependencies = [ 547 | "memchr", 548 | ] 549 | 550 | [[package]] 551 | name = "once_cell" 552 | version = "1.19.0" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 555 | 556 | [[package]] 557 | name = "parse-zoneinfo" 558 | version = "0.3.0" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" 561 | dependencies = [ 562 | "regex", 563 | ] 564 | 565 | [[package]] 566 | name = "percent-encoding" 567 | version = "2.3.1" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 570 | 571 | [[package]] 572 | name = "phf" 573 | version = "0.7.24" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" 576 | dependencies = [ 577 | "phf_shared 0.7.24", 578 | ] 579 | 580 | [[package]] 581 | name = "phf" 582 | version = "0.11.2" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" 585 | dependencies = [ 586 | "phf_shared 0.11.2", 587 | ] 588 | 589 | [[package]] 590 | name = "phf_codegen" 591 | version = "0.7.24" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" 594 | dependencies = [ 595 | "phf_generator 0.7.24", 596 | "phf_shared 0.7.24", 597 | ] 598 | 599 | [[package]] 600 | name = "phf_codegen" 601 | version = "0.11.2" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" 604 | dependencies = [ 605 | "phf_generator 0.11.2", 606 | "phf_shared 0.11.2", 607 | ] 608 | 609 | [[package]] 610 | name = "phf_generator" 611 | version = "0.7.24" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" 614 | dependencies = [ 615 | "phf_shared 0.7.24", 616 | "rand 0.6.5", 617 | ] 618 | 619 | [[package]] 620 | name = "phf_generator" 621 | version = "0.11.2" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" 624 | dependencies = [ 625 | "phf_shared 0.11.2", 626 | "rand 0.8.5", 627 | ] 628 | 629 | [[package]] 630 | name = "phf_shared" 631 | version = "0.7.24" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" 634 | dependencies = [ 635 | "siphasher 0.2.3", 636 | ] 637 | 638 | [[package]] 639 | name = "phf_shared" 640 | version = "0.11.2" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" 643 | dependencies = [ 644 | "siphasher 0.3.11", 645 | ] 646 | 647 | [[package]] 648 | name = "pin-project" 649 | version = "1.1.5" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" 652 | dependencies = [ 653 | "pin-project-internal", 654 | ] 655 | 656 | [[package]] 657 | name = "pin-project-internal" 658 | version = "1.1.5" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" 661 | dependencies = [ 662 | "proc-macro2 1.0.79", 663 | "quote 1.0.36", 664 | "syn 2.0.58", 665 | ] 666 | 667 | [[package]] 668 | name = "pin-project-lite" 669 | version = "0.2.14" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 672 | 673 | [[package]] 674 | name = "pin-utils" 675 | version = "0.1.0" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 678 | 679 | [[package]] 680 | name = "png" 681 | version = "0.16.8" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" 684 | dependencies = [ 685 | "bitflags", 686 | "crc32fast", 687 | "deflate", 688 | "miniz_oxide 0.3.7", 689 | ] 690 | 691 | [[package]] 692 | name = "precomputed-hash" 693 | version = "0.1.1" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" 696 | 697 | [[package]] 698 | name = "proc-macro2" 699 | version = "0.4.30" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" 702 | dependencies = [ 703 | "unicode-xid", 704 | ] 705 | 706 | [[package]] 707 | name = "proc-macro2" 708 | version = "1.0.79" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 711 | dependencies = [ 712 | "unicode-ident", 713 | ] 714 | 715 | [[package]] 716 | name = "quote" 717 | version = "0.6.13" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" 720 | dependencies = [ 721 | "proc-macro2 0.4.30", 722 | ] 723 | 724 | [[package]] 725 | name = "quote" 726 | version = "1.0.36" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 729 | dependencies = [ 730 | "proc-macro2 1.0.79", 731 | ] 732 | 733 | [[package]] 734 | name = "rand" 735 | version = "0.6.5" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 738 | dependencies = [ 739 | "autocfg 0.1.8", 740 | "libc", 741 | "rand_chacha", 742 | "rand_core 0.4.2", 743 | "rand_hc", 744 | "rand_isaac", 745 | "rand_jitter", 746 | "rand_os", 747 | "rand_pcg", 748 | "rand_xorshift", 749 | "winapi", 750 | ] 751 | 752 | [[package]] 753 | name = "rand" 754 | version = "0.8.5" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 757 | dependencies = [ 758 | "rand_core 0.6.4", 759 | ] 760 | 761 | [[package]] 762 | name = "rand_chacha" 763 | version = "0.1.1" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 766 | dependencies = [ 767 | "autocfg 0.1.8", 768 | "rand_core 0.3.1", 769 | ] 770 | 771 | [[package]] 772 | name = "rand_core" 773 | version = "0.3.1" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 776 | dependencies = [ 777 | "rand_core 0.4.2", 778 | ] 779 | 780 | [[package]] 781 | name = "rand_core" 782 | version = "0.4.2" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" 785 | 786 | [[package]] 787 | name = "rand_core" 788 | version = "0.6.4" 789 | source = "registry+https://github.com/rust-lang/crates.io-index" 790 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 791 | 792 | [[package]] 793 | name = "rand_hc" 794 | version = "0.1.0" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 797 | dependencies = [ 798 | "rand_core 0.3.1", 799 | ] 800 | 801 | [[package]] 802 | name = "rand_isaac" 803 | version = "0.1.1" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 806 | dependencies = [ 807 | "rand_core 0.3.1", 808 | ] 809 | 810 | [[package]] 811 | name = "rand_jitter" 812 | version = "0.1.4" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" 815 | dependencies = [ 816 | "libc", 817 | "rand_core 0.4.2", 818 | "winapi", 819 | ] 820 | 821 | [[package]] 822 | name = "rand_os" 823 | version = "0.1.3" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" 826 | dependencies = [ 827 | "cloudabi", 828 | "fuchsia-cprng", 829 | "libc", 830 | "rand_core 0.4.2", 831 | "rdrand", 832 | "winapi", 833 | ] 834 | 835 | [[package]] 836 | name = "rand_pcg" 837 | version = "0.1.2" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" 840 | dependencies = [ 841 | "autocfg 0.1.8", 842 | "rand_core 0.4.2", 843 | ] 844 | 845 | [[package]] 846 | name = "rand_xorshift" 847 | version = "0.1.1" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 850 | dependencies = [ 851 | "rand_core 0.3.1", 852 | ] 853 | 854 | [[package]] 855 | name = "rayon" 856 | version = "1.10.0" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 859 | dependencies = [ 860 | "either", 861 | "rayon-core", 862 | ] 863 | 864 | [[package]] 865 | name = "rayon-core" 866 | version = "1.12.1" 867 | source = "registry+https://github.com/rust-lang/crates.io-index" 868 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 869 | dependencies = [ 870 | "crossbeam-deque", 871 | "crossbeam-utils", 872 | ] 873 | 874 | [[package]] 875 | name = "rdrand" 876 | version = "0.4.0" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 879 | dependencies = [ 880 | "rand_core 0.3.1", 881 | ] 882 | 883 | [[package]] 884 | name = "regex" 885 | version = "1.10.4" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 888 | dependencies = [ 889 | "aho-corasick", 890 | "memchr", 891 | "regex-automata", 892 | "regex-syntax", 893 | ] 894 | 895 | [[package]] 896 | name = "regex-automata" 897 | version = "0.4.6" 898 | source = "registry+https://github.com/rust-lang/crates.io-index" 899 | checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" 900 | dependencies = [ 901 | "aho-corasick", 902 | "memchr", 903 | "regex-syntax", 904 | ] 905 | 906 | [[package]] 907 | name = "regex-syntax" 908 | version = "0.8.3" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" 911 | 912 | [[package]] 913 | name = "rustc-demangle" 914 | version = "0.1.23" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 917 | 918 | [[package]] 919 | name = "ryu" 920 | version = "1.0.17" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" 923 | 924 | [[package]] 925 | name = "scoped_threadpool" 926 | version = "0.1.9" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" 929 | 930 | [[package]] 931 | name = "serde" 932 | version = "1.0.197" 933 | source = "registry+https://github.com/rust-lang/crates.io-index" 934 | checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" 935 | dependencies = [ 936 | "serde_derive", 937 | ] 938 | 939 | [[package]] 940 | name = "serde-wasm-bindgen" 941 | version = "0.5.0" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" 944 | dependencies = [ 945 | "js-sys", 946 | "serde", 947 | "wasm-bindgen", 948 | ] 949 | 950 | [[package]] 951 | name = "serde_derive" 952 | version = "1.0.197" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" 955 | dependencies = [ 956 | "proc-macro2 1.0.79", 957 | "quote 1.0.36", 958 | "syn 2.0.58", 959 | ] 960 | 961 | [[package]] 962 | name = "serde_json" 963 | version = "1.0.115" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" 966 | dependencies = [ 967 | "itoa", 968 | "ryu", 969 | "serde", 970 | ] 971 | 972 | [[package]] 973 | name = "siphasher" 974 | version = "0.2.3" 975 | source = "registry+https://github.com/rust-lang/crates.io-index" 976 | checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" 977 | 978 | [[package]] 979 | name = "siphasher" 980 | version = "0.3.11" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 983 | 984 | [[package]] 985 | name = "slab" 986 | version = "0.4.9" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 989 | dependencies = [ 990 | "autocfg 1.2.0", 991 | ] 992 | 993 | [[package]] 994 | name = "soup" 995 | version = "0.5.1" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | checksum = "aa5a5d21523f4b7a17ad04eaf534360fc908879f53f3341918cbec2fee9cfe14" 998 | dependencies = [ 999 | "html5ever", 1000 | "regex", 1001 | ] 1002 | 1003 | [[package]] 1004 | name = "string_cache" 1005 | version = "0.7.5" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "89c058a82f9fd69b1becf8c274f412281038877c553182f1d02eb027045a2d67" 1008 | dependencies = [ 1009 | "lazy_static", 1010 | "new_debug_unreachable", 1011 | "phf_shared 0.7.24", 1012 | "precomputed-hash", 1013 | "serde", 1014 | "string_cache_codegen", 1015 | "string_cache_shared", 1016 | ] 1017 | 1018 | [[package]] 1019 | name = "string_cache_codegen" 1020 | version = "0.4.4" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6" 1023 | dependencies = [ 1024 | "phf_generator 0.7.24", 1025 | "phf_shared 0.7.24", 1026 | "proc-macro2 1.0.79", 1027 | "quote 1.0.36", 1028 | "string_cache_shared", 1029 | ] 1030 | 1031 | [[package]] 1032 | name = "string_cache_shared" 1033 | version = "0.3.0" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" 1036 | 1037 | [[package]] 1038 | name = "syn" 1039 | version = "0.15.44" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" 1042 | dependencies = [ 1043 | "proc-macro2 0.4.30", 1044 | "quote 0.6.13", 1045 | "unicode-xid", 1046 | ] 1047 | 1048 | [[package]] 1049 | name = "syn" 1050 | version = "2.0.58" 1051 | source = "registry+https://github.com/rust-lang/crates.io-index" 1052 | checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" 1053 | dependencies = [ 1054 | "proc-macro2 1.0.79", 1055 | "quote 1.0.36", 1056 | "unicode-ident", 1057 | ] 1058 | 1059 | [[package]] 1060 | name = "tendril" 1061 | version = "0.4.3" 1062 | source = "registry+https://github.com/rust-lang/crates.io-index" 1063 | checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" 1064 | dependencies = [ 1065 | "futf", 1066 | "mac", 1067 | "utf-8", 1068 | ] 1069 | 1070 | [[package]] 1071 | name = "thiserror" 1072 | version = "1.0.58" 1073 | source = "registry+https://github.com/rust-lang/crates.io-index" 1074 | checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" 1075 | dependencies = [ 1076 | "thiserror-impl", 1077 | ] 1078 | 1079 | [[package]] 1080 | name = "thiserror-impl" 1081 | version = "1.0.58" 1082 | source = "registry+https://github.com/rust-lang/crates.io-index" 1083 | checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" 1084 | dependencies = [ 1085 | "proc-macro2 1.0.79", 1086 | "quote 1.0.36", 1087 | "syn 2.0.58", 1088 | ] 1089 | 1090 | [[package]] 1091 | name = "tiff" 1092 | version = "0.6.1" 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" 1094 | checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" 1095 | dependencies = [ 1096 | "jpeg-decoder", 1097 | "miniz_oxide 0.4.4", 1098 | "weezl", 1099 | ] 1100 | 1101 | [[package]] 1102 | name = "tinyvec" 1103 | version = "1.6.0" 1104 | source = "registry+https://github.com/rust-lang/crates.io-index" 1105 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1106 | dependencies = [ 1107 | "tinyvec_macros", 1108 | ] 1109 | 1110 | [[package]] 1111 | name = "tinyvec_macros" 1112 | version = "0.1.1" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1115 | 1116 | [[package]] 1117 | name = "tokio" 1118 | version = "1.37.0" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" 1121 | dependencies = [ 1122 | "backtrace", 1123 | "pin-project-lite", 1124 | ] 1125 | 1126 | [[package]] 1127 | name = "unicode-bidi" 1128 | version = "0.3.15" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 1131 | 1132 | [[package]] 1133 | name = "unicode-ident" 1134 | version = "1.0.12" 1135 | source = "registry+https://github.com/rust-lang/crates.io-index" 1136 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1137 | 1138 | [[package]] 1139 | name = "unicode-normalization" 1140 | version = "0.1.23" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" 1143 | dependencies = [ 1144 | "tinyvec", 1145 | ] 1146 | 1147 | [[package]] 1148 | name = "unicode-xid" 1149 | version = "0.1.0" 1150 | source = "registry+https://github.com/rust-lang/crates.io-index" 1151 | checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 1152 | 1153 | [[package]] 1154 | name = "url" 1155 | version = "2.5.0" 1156 | source = "registry+https://github.com/rust-lang/crates.io-index" 1157 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" 1158 | dependencies = [ 1159 | "form_urlencoded", 1160 | "idna", 1161 | "percent-encoding", 1162 | ] 1163 | 1164 | [[package]] 1165 | name = "utf-8" 1166 | version = "0.7.6" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 1169 | 1170 | [[package]] 1171 | name = "wasm-bindgen" 1172 | version = "0.2.86" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" 1175 | dependencies = [ 1176 | "cfg-if", 1177 | "wasm-bindgen-macro", 1178 | ] 1179 | 1180 | [[package]] 1181 | name = "wasm-bindgen-backend" 1182 | version = "0.2.86" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" 1185 | dependencies = [ 1186 | "bumpalo", 1187 | "log", 1188 | "once_cell", 1189 | "proc-macro2 1.0.79", 1190 | "quote 1.0.36", 1191 | "syn 2.0.58", 1192 | "wasm-bindgen-shared", 1193 | ] 1194 | 1195 | [[package]] 1196 | name = "wasm-bindgen-futures" 1197 | version = "0.4.36" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" 1200 | dependencies = [ 1201 | "cfg-if", 1202 | "js-sys", 1203 | "wasm-bindgen", 1204 | "web-sys", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "wasm-bindgen-macro" 1209 | version = "0.2.86" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" 1212 | dependencies = [ 1213 | "quote 1.0.36", 1214 | "wasm-bindgen-macro-support", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "wasm-bindgen-macro-support" 1219 | version = "0.2.86" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" 1222 | dependencies = [ 1223 | "proc-macro2 1.0.79", 1224 | "quote 1.0.36", 1225 | "syn 2.0.58", 1226 | "wasm-bindgen-backend", 1227 | "wasm-bindgen-shared", 1228 | ] 1229 | 1230 | [[package]] 1231 | name = "wasm-bindgen-shared" 1232 | version = "0.2.86" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" 1235 | 1236 | [[package]] 1237 | name = "wasm-streams" 1238 | version = "0.3.0" 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" 1240 | checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" 1241 | dependencies = [ 1242 | "futures-util", 1243 | "js-sys", 1244 | "wasm-bindgen", 1245 | "wasm-bindgen-futures", 1246 | "web-sys", 1247 | ] 1248 | 1249 | [[package]] 1250 | name = "web-sys" 1251 | version = "0.3.63" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" 1254 | dependencies = [ 1255 | "js-sys", 1256 | "wasm-bindgen", 1257 | ] 1258 | 1259 | [[package]] 1260 | name = "weezl" 1261 | version = "0.1.8" 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" 1263 | checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" 1264 | 1265 | [[package]] 1266 | name = "winapi" 1267 | version = "0.3.9" 1268 | source = "registry+https://github.com/rust-lang/crates.io-index" 1269 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1270 | dependencies = [ 1271 | "winapi-i686-pc-windows-gnu", 1272 | "winapi-x86_64-pc-windows-gnu", 1273 | ] 1274 | 1275 | [[package]] 1276 | name = "winapi-i686-pc-windows-gnu" 1277 | version = "0.4.0" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1280 | 1281 | [[package]] 1282 | name = "winapi-x86_64-pc-windows-gnu" 1283 | version = "0.4.0" 1284 | source = "registry+https://github.com/rust-lang/crates.io-index" 1285 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1286 | 1287 | [[package]] 1288 | name = "worker" 1289 | version = "0.0.18" 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" 1291 | checksum = "9cd7ad167392bdd707a963356f3478844019c74fc89f6af0dfc656914b30af24" 1292 | dependencies = [ 1293 | "async-trait", 1294 | "chrono", 1295 | "chrono-tz", 1296 | "futures-channel", 1297 | "futures-util", 1298 | "http", 1299 | "js-sys", 1300 | "matchit", 1301 | "pin-project", 1302 | "serde", 1303 | "serde-wasm-bindgen", 1304 | "serde_json", 1305 | "tokio", 1306 | "url", 1307 | "wasm-bindgen", 1308 | "wasm-bindgen-futures", 1309 | "wasm-streams", 1310 | "web-sys", 1311 | "worker-kv", 1312 | "worker-macros", 1313 | "worker-sys", 1314 | ] 1315 | 1316 | [[package]] 1317 | name = "worker-kv" 1318 | version = "0.6.0" 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" 1320 | checksum = "3d4b9fe1a87b7aef252fceb4f30bf6303036a5de329c81ccad9be9c35d1fdbc7" 1321 | dependencies = [ 1322 | "js-sys", 1323 | "serde", 1324 | "serde-wasm-bindgen", 1325 | "serde_json", 1326 | "thiserror", 1327 | "wasm-bindgen", 1328 | "wasm-bindgen-futures", 1329 | ] 1330 | 1331 | [[package]] 1332 | name = "worker-macros" 1333 | version = "0.0.10" 1334 | source = "registry+https://github.com/rust-lang/crates.io-index" 1335 | checksum = "306c6b6fc316ce129de9cc393dc614b244afb37d43d8ae7a4dccf45d6f8a5ff5" 1336 | dependencies = [ 1337 | "async-trait", 1338 | "proc-macro2 1.0.79", 1339 | "quote 1.0.36", 1340 | "syn 2.0.58", 1341 | "wasm-bindgen", 1342 | "wasm-bindgen-futures", 1343 | "wasm-bindgen-macro-support", 1344 | "worker-sys", 1345 | ] 1346 | 1347 | [[package]] 1348 | name = "worker-sys" 1349 | version = "0.0.10" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "8f5db3bd0e45980dbcefe567c978b4930e4526e864cd9e70482252a60229ddd7" 1352 | dependencies = [ 1353 | "cfg-if", 1354 | "js-sys", 1355 | "wasm-bindgen", 1356 | "web-sys", 1357 | ] 1358 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "favicon-rustler" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | 9 | [dependencies] 10 | url = "2.2.2" 11 | soup = "0.5.1" 12 | worker = "0.0.18" 13 | image = "0.23.14" # Check for the latest version that might better support WASM 14 | log = "0.4" 15 | wasm-bindgen = "0.2" 16 | serde_json = "1.0" 17 | 18 | [profile.release] 19 | opt-level = "s" # optimize for size in release builds 20 | lto = true 21 | strip = true 22 | codegen-units = 1 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "favicon-rustler", 3 | "version": "0.1.0", 4 | "private": false, 5 | "scripts": { 6 | "deploy": "wrangler deploy", 7 | "dev": "wrangler dev --env dev" 8 | }, 9 | "devDependencies": { 10 | "wrangler": "^3.1.2" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use worker::*; 2 | mod utils; 3 | use utils::{find_icon_url, fetch_and_scale_icon}; 4 | 5 | #[event(fetch)] 6 | pub async fn main(req: Request, _env: Env, _ctx: Context) -> Result { 7 | let url = req.url()?; 8 | let path_segments = url.path_segments().map(|c| c.collect::>()).unwrap_or_default(); 9 | 10 | if path_segments.len() < 2 { 11 | return Response::error("URL must be in the format /[url-to-website]/[size]", 400); 12 | } 13 | 14 | let target_url = format!("https://{}", path_segments[0]); 15 | let size = path_segments.get(1).and_then(|s| s.parse::().ok()).unwrap_or(64); 16 | 17 | if size > 512 { 18 | return Response::error("Maximum size is 512 pixels", 400); 19 | } 20 | 21 | match utils::is_website_up(&target_url).await { 22 | Ok(true) => {}, 23 | Ok(false) => return Response::error("Website is not accessible", 404), 24 | Err(_) => return Response::error("Failed to check website accessibility", 500), 25 | } 26 | 27 | let icon_url = match find_icon_url(&target_url).await { 28 | Ok(Some(url)) => url, 29 | Ok(None) => return Response::error("No icon found", 404), 30 | Err(_) => return Response::error("Error finding icon", 500), 31 | }; 32 | 33 | match fetch_and_scale_icon(&icon_url, size).await { 34 | Ok(data) => { 35 | let mut headers = Headers::new(); 36 | headers.set("Content-Type", "image/png")?; 37 | Response::from_bytes(data).map(|resp| resp.with_headers(headers)) 38 | }, 39 | Err(_) => Response::error("Failed to fetch or scale the icon", 500), 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use worker::*; 2 | use std::fmt; 3 | use soup::{Soup, QueryBuilderExt, NodeExt}; 4 | use url::Url as StdUrl; 5 | use image::{ImageError, ImageOutputFormat}; 6 | use serde_json::Value as JsonValue; 7 | 8 | pub async fn is_website_up(url: &str) -> Result { 9 | let response = Fetch::Url(Url::parse(url)?).send().await?; 10 | Ok(response.status_code() >= 200 && response.status_code() < 300) 11 | } 12 | 13 | pub struct MyImageError(ImageError); 14 | 15 | impl From for worker::Error { 16 | fn from(err: MyImageError) -> Self { 17 | worker::Error::from(err.0.to_string()) 18 | } 19 | } 20 | 21 | impl fmt::Display for MyImageError { 22 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 23 | write!(f, "{}", self.0.to_string()) 24 | } 25 | } 26 | 27 | /// Finds the icon URL from the given website's HTML content or manifest 28 | pub async fn find_icon_url(url: &str) -> Result> { 29 | let mut response = Fetch::Url(Url::parse(url)?).send().await?; 30 | let html = response.text().await?; 31 | let soup = Soup::new(&html); 32 | let base_url = StdUrl::parse(url)?; 33 | 34 | let icons = [ 35 | ("apple-touch-icon", "href"), 36 | ("icon", "href"), 37 | ("shortcut icon", "href"), 38 | ("link[rel='manifest']", "href"), 39 | ]; 40 | 41 | console_log!("Fetching icon from URL: {}", url); 42 | 43 | for &(icon, attr) in &icons { 44 | console_log!("Searching for icons of type: {}", icon); 45 | let elements = soup.tag(icon.split_once('[').unwrap_or((icon, "")).0).find_all(); 46 | 47 | for element in elements { 48 | if let Some(link) = element.get(attr) { 49 | if icon == "link[rel='manifest']" { 50 | if let Ok(Some(icon_url)) = process_manifest(&link, &base_url).await { 51 | return Ok(Some(icon_url)); 52 | } 53 | } else { 54 | let full_url = match link.starts_with("http://") || link.starts_with("https://") { 55 | true => link.to_string(), // Already absolute URL 56 | false => base_url.join(&link)?.to_string(), // Resolve relative URL 57 | }; 58 | console_log!("Icon found: {}", full_url); 59 | return Ok(Some(full_url)); 60 | } 61 | } 62 | } 63 | } 64 | 65 | // Check well-known locations 66 | let well_known_icons = ["favicon.ico", "favicon.png", "apple-touch-icon.png"]; 67 | for icon in well_known_icons.iter() { 68 | let icon_url = base_url.join(icon)?; 69 | 70 | if let Ok(true) = check_url_exists(&icon_url.to_string()).await { 71 | console_log!("Icon found in well-known location: {}", icon_url); 72 | return Ok(Some(icon_url.to_string())); 73 | } else { 74 | console_log!("Failed to find icon in well-known location: {}", icon_url); 75 | } 76 | } 77 | 78 | // Specific handling for meta tags with property="og:image" 79 | if let Some(og_image) = soup.tag("meta").attr("property", "og:image").find() { 80 | if let Some(content) = og_image.get("content") { 81 | let full_url = validate_and_construct_url(&content, &base_url)?; 82 | console_log!("OG Image found: {}", full_url); 83 | return Ok(Some(full_url)); 84 | } 85 | } 86 | 87 | // Fallback to external service 88 | let fallback_url = format!("https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url={}&size=128", url); 89 | if let Ok(true) = check_url_exists(&fallback_url).await { 90 | console_log!("Icon found using fallback service: {}", fallback_url); 91 | return Ok(Some(fallback_url)); 92 | } else { 93 | console_log!("Failed to verify icon at fallback service: {}", fallback_url); 94 | } 95 | console_log!("No icon found for URL: {}", url); 96 | Ok(None) 97 | } 98 | 99 | /// Validate and construct the full URL from a potential relative link 100 | fn validate_and_construct_url(link: &str, base_url: &StdUrl) -> Result { 101 | if link.starts_with("http://") || link.starts_with("https://") { 102 | Ok(link.to_string()) 103 | } else { 104 | base_url.join(link).map_err(|e| worker::Error::from(e.to_string())).map(|url| url.to_string()) 105 | } 106 | } 107 | 108 | /// Processes a manifest file to find icons 109 | async fn process_manifest(manifest_url: &str, base_url: &StdUrl) -> Result> { 110 | // Parse the URL from the string, handling errors appropriately 111 | let parsed_url = StdUrl::parse(manifest_url).map_err(|e| worker::Error::from(e.to_string()))?; 112 | 113 | // Perform the fetch operation 114 | let mut response = Fetch::Url(Url::parse(&parsed_url.to_string())?) 115 | .send() 116 | .await 117 | .map_err(|e| worker::Error::from(e.to_string()))?; 118 | 119 | // Attempt to deserialize the JSON response 120 | let manifest: JsonValue = response.json::().await 121 | .map_err(|e| worker::Error::from(e.to_string()))?; 122 | 123 | // Look for the 'icons' array in the JSON structure 124 | if let Some(icons) = manifest["icons"].as_array() { 125 | for icon in icons { 126 | if let Some(icon_src) = icon["src"].as_str() { 127 | // Construct the full URL based on whether it's relative or absolute 128 | let full_url = match icon_src.starts_with("http://") || icon_src.starts_with("https://") { 129 | true => icon_src.to_string(), 130 | false => base_url.join(icon_src).map_err(|e| worker::Error::from(e.to_string()))?.to_string(), 131 | }; 132 | return Ok(Some(full_url)); 133 | } 134 | } 135 | } 136 | Ok(None) 137 | } 138 | 139 | 140 | /// Checks if a URL exists by performing a HEAD request 141 | async fn check_url_exists(url: &str) -> Result { 142 | let parsed_url = StdUrl::parse(url).map_err(|e| worker::Error::from(e.to_string()))?; 143 | let request = Request::new(&parsed_url.to_string(), Method::Head)?; 144 | let response = Fetch::Request(request).send().await.map_err(|e| worker::Error::from(e.to_string()))?; 145 | Ok(response.status_code() == 200) 146 | } 147 | 148 | 149 | /// Fetches an image from the given URL, resizes it, and returns the raw bytes of the resized image. 150 | pub async fn fetch_and_scale_icon(url: &str, size: u32) -> Result> { 151 | let mut response = Fetch::Url(Url::parse(url)?).send().await?; 152 | if response.status_code() >= 200 && response.status_code() < 300 { 153 | let bytes = response.bytes().await?; 154 | resize_image(&bytes, size) // Directly use the function without external map_err 155 | } else { 156 | Err(worker::Error::from(format!("Failed to fetch the original image: HTTP {}", response.status_code()))) 157 | } 158 | } 159 | 160 | 161 | /// Resizes the image to the specified dimensions using the `image` crate. 162 | fn resize_image(image_data: &[u8], size: u32) -> Result> { 163 | let img = image::load_from_memory(image_data).map_err(MyImageError)?; 164 | let scaled = img.resize_exact(size, size, image::imageops::FilterType::Nearest); 165 | let mut result = Vec::new(); 166 | scaled.write_to(&mut result, ImageOutputFormat::Png).map_err(MyImageError)?; 167 | Ok(result) 168 | } 169 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "worker-rust" 2 | main = "build/worker/shim.mjs" 3 | compatibility_date = "2023-12-01" 4 | 5 | [build] 6 | command = "cargo install -q worker-build && worker-build --release" 7 | 8 | [env.dev] 9 | build = { command = "cargo install -q worker-build && worker-build --dev" } 10 | --------------------------------------------------------------------------------