├── .cargo └── config.toml ├── .github └── workflows │ └── frontend.yaml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── README.md ├── examples └── websocket-demo │ ├── .cargo │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── index.html │ └── src │ ├── macros │ └── mod.rs │ └── main.rs └── src ├── format.rs ├── lib.rs └── websocket.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = [ "--cfg=web_sys_unstable_apis" ] 3 | 4 | [net] 5 | git-fetch-with-cli = true 6 | -------------------------------------------------------------------------------- /.github/workflows/frontend.yaml: -------------------------------------------------------------------------------- 1 | # Based on https://github.com/actions-rs/meta/blob/master/recipes/quickstart.md 2 | 3 | on: [pull_request] 4 | 5 | name: check frontend 6 | 7 | env: 8 | ACTIX_PORT: 8080 9 | 10 | jobs: 11 | test: 12 | name: cargo test 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: dtolnay/rust-toolchain@1.73 17 | with: 18 | components: clippy, rustfmt 19 | - run: cargo fmt --check 20 | - run: cargo test 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | target 3 | .gitignore 4 | -------------------------------------------------------------------------------- /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 = "anyhow" 22 | version = "1.0.80" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" 25 | 26 | [[package]] 27 | name = "anymap2" 28 | version = "0.13.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" 31 | 32 | [[package]] 33 | name = "autocfg" 34 | version = "1.1.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 37 | 38 | [[package]] 39 | name = "backtrace" 40 | version = "0.3.69" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 43 | dependencies = [ 44 | "addr2line", 45 | "cc", 46 | "cfg-if", 47 | "libc", 48 | "miniz_oxide", 49 | "object", 50 | "rustc-demangle", 51 | ] 52 | 53 | [[package]] 54 | name = "bincode" 55 | version = "1.3.3" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 58 | dependencies = [ 59 | "serde", 60 | ] 61 | 62 | [[package]] 63 | name = "boolinator" 64 | version = "2.4.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" 67 | 68 | [[package]] 69 | name = "bumpalo" 70 | version = "3.15.1" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "c764d619ca78fccbf3069b37bd7af92577f044bb15236036662d79b6559f25b7" 73 | 74 | [[package]] 75 | name = "byteorder" 76 | version = "1.5.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 79 | 80 | [[package]] 81 | name = "bytes" 82 | version = "1.5.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" 85 | 86 | [[package]] 87 | name = "cc" 88 | version = "1.0.86" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" 91 | 92 | [[package]] 93 | name = "cfg-if" 94 | version = "1.0.0" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 97 | 98 | [[package]] 99 | name = "console_error_panic_hook" 100 | version = "0.1.7" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 103 | dependencies = [ 104 | "cfg-if", 105 | "wasm-bindgen", 106 | ] 107 | 108 | [[package]] 109 | name = "equivalent" 110 | version = "1.0.1" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 113 | 114 | [[package]] 115 | name = "fnv" 116 | version = "1.0.7" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 119 | 120 | [[package]] 121 | name = "form_urlencoded" 122 | version = "1.2.1" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 125 | dependencies = [ 126 | "percent-encoding", 127 | ] 128 | 129 | [[package]] 130 | name = "futures" 131 | version = "0.3.30" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" 134 | dependencies = [ 135 | "futures-channel", 136 | "futures-core", 137 | "futures-executor", 138 | "futures-io", 139 | "futures-sink", 140 | "futures-task", 141 | "futures-util", 142 | ] 143 | 144 | [[package]] 145 | name = "futures-channel" 146 | version = "0.3.30" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 149 | dependencies = [ 150 | "futures-core", 151 | "futures-sink", 152 | ] 153 | 154 | [[package]] 155 | name = "futures-core" 156 | version = "0.3.30" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 159 | 160 | [[package]] 161 | name = "futures-executor" 162 | version = "0.3.30" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 165 | dependencies = [ 166 | "futures-core", 167 | "futures-task", 168 | "futures-util", 169 | ] 170 | 171 | [[package]] 172 | name = "futures-io" 173 | version = "0.3.30" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 176 | 177 | [[package]] 178 | name = "futures-macro" 179 | version = "0.3.30" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 182 | dependencies = [ 183 | "proc-macro2", 184 | "quote", 185 | "syn 2.0.50", 186 | ] 187 | 188 | [[package]] 189 | name = "futures-sink" 190 | version = "0.3.30" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 193 | 194 | [[package]] 195 | name = "futures-task" 196 | version = "0.3.30" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 199 | 200 | [[package]] 201 | name = "futures-util" 202 | version = "0.3.30" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 205 | dependencies = [ 206 | "futures-channel", 207 | "futures-core", 208 | "futures-io", 209 | "futures-macro", 210 | "futures-sink", 211 | "futures-task", 212 | "memchr", 213 | "pin-project-lite", 214 | "pin-utils", 215 | "slab", 216 | ] 217 | 218 | [[package]] 219 | name = "getrandom" 220 | version = "0.2.12" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" 223 | dependencies = [ 224 | "cfg-if", 225 | "js-sys", 226 | "libc", 227 | "wasi", 228 | "wasm-bindgen", 229 | ] 230 | 231 | [[package]] 232 | name = "gimli" 233 | version = "0.28.1" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 236 | 237 | [[package]] 238 | name = "gloo" 239 | version = "0.8.1" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "28999cda5ef6916ffd33fb4a7b87e1de633c47c0dc6d97905fee1cdaa142b94d" 242 | dependencies = [ 243 | "gloo-console 0.2.3", 244 | "gloo-dialogs 0.1.1", 245 | "gloo-events 0.1.2", 246 | "gloo-file 0.2.3", 247 | "gloo-history 0.1.5", 248 | "gloo-net 0.3.1", 249 | "gloo-render 0.1.1", 250 | "gloo-storage 0.2.2", 251 | "gloo-timers 0.2.6", 252 | "gloo-utils 0.1.7", 253 | "gloo-worker 0.2.1", 254 | ] 255 | 256 | [[package]] 257 | name = "gloo" 258 | version = "0.10.0" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "cd35526c28cc55c1db77aed6296de58677dbab863b118483a27845631d870249" 261 | dependencies = [ 262 | "gloo-console 0.3.0", 263 | "gloo-dialogs 0.2.0", 264 | "gloo-events 0.2.0", 265 | "gloo-file 0.3.0", 266 | "gloo-history 0.2.2", 267 | "gloo-net 0.4.0", 268 | "gloo-render 0.2.0", 269 | "gloo-storage 0.3.0", 270 | "gloo-timers 0.3.0", 271 | "gloo-utils 0.2.0", 272 | "gloo-worker 0.4.0", 273 | ] 274 | 275 | [[package]] 276 | name = "gloo-console" 277 | version = "0.2.3" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" 280 | dependencies = [ 281 | "gloo-utils 0.1.7", 282 | "js-sys", 283 | "serde", 284 | "wasm-bindgen", 285 | "web-sys", 286 | ] 287 | 288 | [[package]] 289 | name = "gloo-console" 290 | version = "0.3.0" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261" 293 | dependencies = [ 294 | "gloo-utils 0.2.0", 295 | "js-sys", 296 | "serde", 297 | "wasm-bindgen", 298 | "web-sys", 299 | ] 300 | 301 | [[package]] 302 | name = "gloo-dialogs" 303 | version = "0.1.1" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6" 306 | dependencies = [ 307 | "wasm-bindgen", 308 | "web-sys", 309 | ] 310 | 311 | [[package]] 312 | name = "gloo-dialogs" 313 | version = "0.2.0" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "bf4748e10122b01435750ff530095b1217cf6546173459448b83913ebe7815df" 316 | dependencies = [ 317 | "wasm-bindgen", 318 | "web-sys", 319 | ] 320 | 321 | [[package]] 322 | name = "gloo-events" 323 | version = "0.1.2" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc" 326 | dependencies = [ 327 | "wasm-bindgen", 328 | "web-sys", 329 | ] 330 | 331 | [[package]] 332 | name = "gloo-events" 333 | version = "0.2.0" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "27c26fb45f7c385ba980f5fa87ac677e363949e065a083722697ef1b2cc91e41" 336 | dependencies = [ 337 | "wasm-bindgen", 338 | "web-sys", 339 | ] 340 | 341 | [[package]] 342 | name = "gloo-file" 343 | version = "0.2.3" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" 346 | dependencies = [ 347 | "gloo-events 0.1.2", 348 | "js-sys", 349 | "wasm-bindgen", 350 | "web-sys", 351 | ] 352 | 353 | [[package]] 354 | name = "gloo-file" 355 | version = "0.3.0" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f" 358 | dependencies = [ 359 | "gloo-events 0.2.0", 360 | "js-sys", 361 | "wasm-bindgen", 362 | "web-sys", 363 | ] 364 | 365 | [[package]] 366 | name = "gloo-history" 367 | version = "0.1.5" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f" 370 | dependencies = [ 371 | "gloo-events 0.1.2", 372 | "gloo-utils 0.1.7", 373 | "serde", 374 | "serde-wasm-bindgen 0.5.0", 375 | "serde_urlencoded", 376 | "thiserror", 377 | "wasm-bindgen", 378 | "web-sys", 379 | ] 380 | 381 | [[package]] 382 | name = "gloo-history" 383 | version = "0.2.2" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "903f432be5ba34427eac5e16048ef65604a82061fe93789f2212afc73d8617d6" 386 | dependencies = [ 387 | "getrandom", 388 | "gloo-events 0.2.0", 389 | "gloo-utils 0.2.0", 390 | "serde", 391 | "serde-wasm-bindgen 0.6.3", 392 | "serde_urlencoded", 393 | "thiserror", 394 | "wasm-bindgen", 395 | "web-sys", 396 | ] 397 | 398 | [[package]] 399 | name = "gloo-net" 400 | version = "0.2.6" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10" 403 | dependencies = [ 404 | "futures-channel", 405 | "futures-core", 406 | "futures-sink", 407 | "gloo-utils 0.1.7", 408 | "js-sys", 409 | "pin-project", 410 | "serde", 411 | "serde_json", 412 | "thiserror", 413 | "wasm-bindgen", 414 | "wasm-bindgen-futures", 415 | "web-sys", 416 | ] 417 | 418 | [[package]] 419 | name = "gloo-net" 420 | version = "0.3.1" 421 | source = "registry+https://github.com/rust-lang/crates.io-index" 422 | checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620" 423 | dependencies = [ 424 | "futures-channel", 425 | "futures-core", 426 | "futures-sink", 427 | "gloo-utils 0.1.7", 428 | "http", 429 | "js-sys", 430 | "pin-project", 431 | "serde", 432 | "serde_json", 433 | "thiserror", 434 | "wasm-bindgen", 435 | "wasm-bindgen-futures", 436 | "web-sys", 437 | ] 438 | 439 | [[package]] 440 | name = "gloo-net" 441 | version = "0.4.0" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "8ac9e8288ae2c632fa9f8657ac70bfe38a1530f345282d7ba66a1f70b72b7dc4" 444 | dependencies = [ 445 | "futures-channel", 446 | "futures-core", 447 | "futures-sink", 448 | "gloo-utils 0.2.0", 449 | "http", 450 | "js-sys", 451 | "pin-project", 452 | "serde", 453 | "serde_json", 454 | "thiserror", 455 | "wasm-bindgen", 456 | "wasm-bindgen-futures", 457 | "web-sys", 458 | ] 459 | 460 | [[package]] 461 | name = "gloo-render" 462 | version = "0.1.1" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764" 465 | dependencies = [ 466 | "wasm-bindgen", 467 | "web-sys", 468 | ] 469 | 470 | [[package]] 471 | name = "gloo-render" 472 | version = "0.2.0" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "56008b6744713a8e8d98ac3dcb7d06543d5662358c9c805b4ce2167ad4649833" 475 | dependencies = [ 476 | "wasm-bindgen", 477 | "web-sys", 478 | ] 479 | 480 | [[package]] 481 | name = "gloo-storage" 482 | version = "0.2.2" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" 485 | dependencies = [ 486 | "gloo-utils 0.1.7", 487 | "js-sys", 488 | "serde", 489 | "serde_json", 490 | "thiserror", 491 | "wasm-bindgen", 492 | "web-sys", 493 | ] 494 | 495 | [[package]] 496 | name = "gloo-storage" 497 | version = "0.3.0" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" 500 | dependencies = [ 501 | "gloo-utils 0.2.0", 502 | "js-sys", 503 | "serde", 504 | "serde_json", 505 | "thiserror", 506 | "wasm-bindgen", 507 | "web-sys", 508 | ] 509 | 510 | [[package]] 511 | name = "gloo-timers" 512 | version = "0.2.6" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" 515 | dependencies = [ 516 | "js-sys", 517 | "wasm-bindgen", 518 | ] 519 | 520 | [[package]] 521 | name = "gloo-timers" 522 | version = "0.3.0" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" 525 | dependencies = [ 526 | "js-sys", 527 | "wasm-bindgen", 528 | ] 529 | 530 | [[package]] 531 | name = "gloo-utils" 532 | version = "0.1.7" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" 535 | dependencies = [ 536 | "js-sys", 537 | "serde", 538 | "serde_json", 539 | "wasm-bindgen", 540 | "web-sys", 541 | ] 542 | 543 | [[package]] 544 | name = "gloo-utils" 545 | version = "0.2.0" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" 548 | dependencies = [ 549 | "js-sys", 550 | "serde", 551 | "serde_json", 552 | "wasm-bindgen", 553 | "web-sys", 554 | ] 555 | 556 | [[package]] 557 | name = "gloo-worker" 558 | version = "0.2.1" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a" 561 | dependencies = [ 562 | "anymap2", 563 | "bincode", 564 | "gloo-console 0.2.3", 565 | "gloo-utils 0.1.7", 566 | "js-sys", 567 | "serde", 568 | "wasm-bindgen", 569 | "wasm-bindgen-futures", 570 | "web-sys", 571 | ] 572 | 573 | [[package]] 574 | name = "gloo-worker" 575 | version = "0.4.0" 576 | source = "registry+https://github.com/rust-lang/crates.io-index" 577 | checksum = "76495d3dd87de51da268fa3a593da118ab43eb7f8809e17eb38d3319b424e400" 578 | dependencies = [ 579 | "bincode", 580 | "futures", 581 | "gloo-utils 0.2.0", 582 | "gloo-worker-macros", 583 | "js-sys", 584 | "pinned", 585 | "serde", 586 | "thiserror", 587 | "wasm-bindgen", 588 | "wasm-bindgen-futures", 589 | "web-sys", 590 | ] 591 | 592 | [[package]] 593 | name = "gloo-worker-macros" 594 | version = "0.1.0" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "956caa58d4857bc9941749d55e4bd3000032d8212762586fa5705632967140e7" 597 | dependencies = [ 598 | "proc-macro-crate", 599 | "proc-macro2", 600 | "quote", 601 | "syn 2.0.50", 602 | ] 603 | 604 | [[package]] 605 | name = "hashbrown" 606 | version = "0.14.3" 607 | source = "registry+https://github.com/rust-lang/crates.io-index" 608 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" 609 | 610 | [[package]] 611 | name = "hermit-abi" 612 | version = "0.3.6" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" 615 | 616 | [[package]] 617 | name = "http" 618 | version = "0.2.11" 619 | source = "registry+https://github.com/rust-lang/crates.io-index" 620 | checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" 621 | dependencies = [ 622 | "bytes", 623 | "fnv", 624 | "itoa", 625 | ] 626 | 627 | [[package]] 628 | name = "implicit-clone" 629 | version = "0.4.8" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "fc06a255cbf402a52ae399c05a518c68c569c916ea11423620111df576b9b9bb" 632 | dependencies = [ 633 | "implicit-clone-derive", 634 | "indexmap", 635 | ] 636 | 637 | [[package]] 638 | name = "implicit-clone-derive" 639 | version = "0.1.1" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "9311685eb9a34808bbb0608ad2fcab9ae216266beca5848613e95553ac914e3b" 642 | dependencies = [ 643 | "quote", 644 | "syn 2.0.50", 645 | ] 646 | 647 | [[package]] 648 | name = "indexmap" 649 | version = "2.2.3" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" 652 | dependencies = [ 653 | "equivalent", 654 | "hashbrown", 655 | ] 656 | 657 | [[package]] 658 | name = "itoa" 659 | version = "1.0.10" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" 662 | 663 | [[package]] 664 | name = "js-sys" 665 | version = "0.3.68" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" 668 | dependencies = [ 669 | "wasm-bindgen", 670 | ] 671 | 672 | [[package]] 673 | name = "libc" 674 | version = "0.2.153" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 677 | 678 | [[package]] 679 | name = "log" 680 | version = "0.4.20" 681 | source = "registry+https://github.com/rust-lang/crates.io-index" 682 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 683 | 684 | [[package]] 685 | name = "memchr" 686 | version = "2.7.1" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" 689 | 690 | [[package]] 691 | name = "miniz_oxide" 692 | version = "0.7.2" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 695 | dependencies = [ 696 | "adler", 697 | ] 698 | 699 | [[package]] 700 | name = "num-traits" 701 | version = "0.2.18" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" 704 | dependencies = [ 705 | "autocfg", 706 | ] 707 | 708 | [[package]] 709 | name = "num_cpus" 710 | version = "1.16.0" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 713 | dependencies = [ 714 | "hermit-abi", 715 | "libc", 716 | ] 717 | 718 | [[package]] 719 | name = "object" 720 | version = "0.32.2" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 723 | dependencies = [ 724 | "memchr", 725 | ] 726 | 727 | [[package]] 728 | name = "once_cell" 729 | version = "1.19.0" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 732 | 733 | [[package]] 734 | name = "paste" 735 | version = "1.0.14" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" 738 | 739 | [[package]] 740 | name = "percent-encoding" 741 | version = "2.3.1" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 744 | 745 | [[package]] 746 | name = "pin-project" 747 | version = "1.1.4" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" 750 | dependencies = [ 751 | "pin-project-internal", 752 | ] 753 | 754 | [[package]] 755 | name = "pin-project-internal" 756 | version = "1.1.4" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" 759 | dependencies = [ 760 | "proc-macro2", 761 | "quote", 762 | "syn 2.0.50", 763 | ] 764 | 765 | [[package]] 766 | name = "pin-project-lite" 767 | version = "0.2.13" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" 770 | 771 | [[package]] 772 | name = "pin-utils" 773 | version = "0.1.0" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 776 | 777 | [[package]] 778 | name = "pinned" 779 | version = "0.1.0" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b" 782 | dependencies = [ 783 | "futures", 784 | "rustversion", 785 | "thiserror", 786 | ] 787 | 788 | [[package]] 789 | name = "prettyplease" 790 | version = "0.2.16" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" 793 | dependencies = [ 794 | "proc-macro2", 795 | "syn 2.0.50", 796 | ] 797 | 798 | [[package]] 799 | name = "proc-macro-crate" 800 | version = "1.3.1" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" 803 | dependencies = [ 804 | "once_cell", 805 | "toml_edit", 806 | ] 807 | 808 | [[package]] 809 | name = "proc-macro-error" 810 | version = "1.0.4" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 813 | dependencies = [ 814 | "proc-macro-error-attr", 815 | "proc-macro2", 816 | "quote", 817 | "syn 1.0.109", 818 | "version_check", 819 | ] 820 | 821 | [[package]] 822 | name = "proc-macro-error-attr" 823 | version = "1.0.4" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 826 | dependencies = [ 827 | "proc-macro2", 828 | "quote", 829 | "version_check", 830 | ] 831 | 832 | [[package]] 833 | name = "proc-macro2" 834 | version = "1.0.78" 835 | source = "registry+https://github.com/rust-lang/crates.io-index" 836 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" 837 | dependencies = [ 838 | "unicode-ident", 839 | ] 840 | 841 | [[package]] 842 | name = "prokio" 843 | version = "0.1.0" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488" 846 | dependencies = [ 847 | "futures", 848 | "gloo 0.8.1", 849 | "num_cpus", 850 | "once_cell", 851 | "pin-project", 852 | "pinned", 853 | "tokio", 854 | "tokio-stream", 855 | "wasm-bindgen-futures", 856 | ] 857 | 858 | [[package]] 859 | name = "quote" 860 | version = "1.0.35" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 863 | dependencies = [ 864 | "proc-macro2", 865 | ] 866 | 867 | [[package]] 868 | name = "rmp" 869 | version = "0.8.12" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" 872 | dependencies = [ 873 | "byteorder", 874 | "num-traits", 875 | "paste", 876 | ] 877 | 878 | [[package]] 879 | name = "rmp-serde" 880 | version = "1.1.2" 881 | source = "registry+https://github.com/rust-lang/crates.io-index" 882 | checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" 883 | dependencies = [ 884 | "byteorder", 885 | "rmp", 886 | "serde", 887 | ] 888 | 889 | [[package]] 890 | name = "rustc-demangle" 891 | version = "0.1.23" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 894 | 895 | [[package]] 896 | name = "rustversion" 897 | version = "1.0.14" 898 | source = "registry+https://github.com/rust-lang/crates.io-index" 899 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" 900 | 901 | [[package]] 902 | name = "ryu" 903 | version = "1.0.17" 904 | source = "registry+https://github.com/rust-lang/crates.io-index" 905 | checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" 906 | 907 | [[package]] 908 | name = "serde" 909 | version = "1.0.197" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" 912 | dependencies = [ 913 | "serde_derive", 914 | ] 915 | 916 | [[package]] 917 | name = "serde-wasm-bindgen" 918 | version = "0.5.0" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" 921 | dependencies = [ 922 | "js-sys", 923 | "serde", 924 | "wasm-bindgen", 925 | ] 926 | 927 | [[package]] 928 | name = "serde-wasm-bindgen" 929 | version = "0.6.3" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "b9b713f70513ae1f8d92665bbbbda5c295c2cf1da5542881ae5eefe20c9af132" 932 | dependencies = [ 933 | "js-sys", 934 | "serde", 935 | "wasm-bindgen", 936 | ] 937 | 938 | [[package]] 939 | name = "serde_derive" 940 | version = "1.0.197" 941 | source = "registry+https://github.com/rust-lang/crates.io-index" 942 | checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" 943 | dependencies = [ 944 | "proc-macro2", 945 | "quote", 946 | "syn 2.0.50", 947 | ] 948 | 949 | [[package]] 950 | name = "serde_json" 951 | version = "1.0.114" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" 954 | dependencies = [ 955 | "itoa", 956 | "ryu", 957 | "serde", 958 | ] 959 | 960 | [[package]] 961 | name = "serde_urlencoded" 962 | version = "0.7.1" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 965 | dependencies = [ 966 | "form_urlencoded", 967 | "itoa", 968 | "ryu", 969 | "serde", 970 | ] 971 | 972 | [[package]] 973 | name = "slab" 974 | version = "0.4.9" 975 | source = "registry+https://github.com/rust-lang/crates.io-index" 976 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 977 | dependencies = [ 978 | "autocfg", 979 | ] 980 | 981 | [[package]] 982 | name = "syn" 983 | version = "1.0.109" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 986 | dependencies = [ 987 | "proc-macro2", 988 | "unicode-ident", 989 | ] 990 | 991 | [[package]] 992 | name = "syn" 993 | version = "2.0.50" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" 996 | dependencies = [ 997 | "proc-macro2", 998 | "quote", 999 | "unicode-ident", 1000 | ] 1001 | 1002 | [[package]] 1003 | name = "thiserror" 1004 | version = "1.0.57" 1005 | source = "registry+https://github.com/rust-lang/crates.io-index" 1006 | checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" 1007 | dependencies = [ 1008 | "thiserror-impl", 1009 | ] 1010 | 1011 | [[package]] 1012 | name = "thiserror-impl" 1013 | version = "1.0.57" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" 1016 | dependencies = [ 1017 | "proc-macro2", 1018 | "quote", 1019 | "syn 2.0.50", 1020 | ] 1021 | 1022 | [[package]] 1023 | name = "tokio" 1024 | version = "1.36.0" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" 1027 | dependencies = [ 1028 | "backtrace", 1029 | "pin-project-lite", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "tokio-stream" 1034 | version = "0.1.14" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" 1037 | dependencies = [ 1038 | "futures-core", 1039 | "pin-project-lite", 1040 | "tokio", 1041 | ] 1042 | 1043 | [[package]] 1044 | name = "toml_datetime" 1045 | version = "0.6.5" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" 1048 | 1049 | [[package]] 1050 | name = "toml_edit" 1051 | version = "0.19.15" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" 1054 | dependencies = [ 1055 | "indexmap", 1056 | "toml_datetime", 1057 | "winnow", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "tracing" 1062 | version = "0.1.40" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1065 | dependencies = [ 1066 | "pin-project-lite", 1067 | "tracing-attributes", 1068 | "tracing-core", 1069 | ] 1070 | 1071 | [[package]] 1072 | name = "tracing-attributes" 1073 | version = "0.1.27" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 1076 | dependencies = [ 1077 | "proc-macro2", 1078 | "quote", 1079 | "syn 2.0.50", 1080 | ] 1081 | 1082 | [[package]] 1083 | name = "tracing-core" 1084 | version = "0.1.32" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1087 | dependencies = [ 1088 | "once_cell", 1089 | ] 1090 | 1091 | [[package]] 1092 | name = "unicode-ident" 1093 | version = "1.0.12" 1094 | source = "registry+https://github.com/rust-lang/crates.io-index" 1095 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1096 | 1097 | [[package]] 1098 | name = "version_check" 1099 | version = "0.9.4" 1100 | source = "registry+https://github.com/rust-lang/crates.io-index" 1101 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1102 | 1103 | [[package]] 1104 | name = "wasi" 1105 | version = "0.11.0+wasi-snapshot-preview1" 1106 | source = "registry+https://github.com/rust-lang/crates.io-index" 1107 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1108 | 1109 | [[package]] 1110 | name = "wasm-bindgen" 1111 | version = "0.2.91" 1112 | source = "registry+https://github.com/rust-lang/crates.io-index" 1113 | checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" 1114 | dependencies = [ 1115 | "cfg-if", 1116 | "wasm-bindgen-macro", 1117 | ] 1118 | 1119 | [[package]] 1120 | name = "wasm-bindgen-backend" 1121 | version = "0.2.91" 1122 | source = "registry+https://github.com/rust-lang/crates.io-index" 1123 | checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" 1124 | dependencies = [ 1125 | "bumpalo", 1126 | "log", 1127 | "once_cell", 1128 | "proc-macro2", 1129 | "quote", 1130 | "syn 2.0.50", 1131 | "wasm-bindgen-shared", 1132 | ] 1133 | 1134 | [[package]] 1135 | name = "wasm-bindgen-futures" 1136 | version = "0.4.41" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" 1139 | dependencies = [ 1140 | "cfg-if", 1141 | "js-sys", 1142 | "wasm-bindgen", 1143 | "web-sys", 1144 | ] 1145 | 1146 | [[package]] 1147 | name = "wasm-bindgen-macro" 1148 | version = "0.2.91" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" 1151 | dependencies = [ 1152 | "quote", 1153 | "wasm-bindgen-macro-support", 1154 | ] 1155 | 1156 | [[package]] 1157 | name = "wasm-bindgen-macro-support" 1158 | version = "0.2.91" 1159 | source = "registry+https://github.com/rust-lang/crates.io-index" 1160 | checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" 1161 | dependencies = [ 1162 | "proc-macro2", 1163 | "quote", 1164 | "syn 2.0.50", 1165 | "wasm-bindgen-backend", 1166 | "wasm-bindgen-shared", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "wasm-bindgen-shared" 1171 | version = "0.2.91" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" 1174 | 1175 | [[package]] 1176 | name = "web-sys" 1177 | version = "0.3.68" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" 1180 | dependencies = [ 1181 | "js-sys", 1182 | "wasm-bindgen", 1183 | ] 1184 | 1185 | [[package]] 1186 | name = "winnow" 1187 | version = "0.5.40" 1188 | source = "registry+https://github.com/rust-lang/crates.io-index" 1189 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 1190 | dependencies = [ 1191 | "memchr", 1192 | ] 1193 | 1194 | [[package]] 1195 | name = "yew" 1196 | version = "0.21.0" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "5f1a03f255c70c7aa3e9c62e15292f142ede0564123543c1cc0c7a4f31660cac" 1199 | dependencies = [ 1200 | "console_error_panic_hook", 1201 | "futures", 1202 | "gloo 0.10.0", 1203 | "implicit-clone", 1204 | "indexmap", 1205 | "js-sys", 1206 | "prokio", 1207 | "rustversion", 1208 | "serde", 1209 | "slab", 1210 | "thiserror", 1211 | "tokio", 1212 | "tracing", 1213 | "wasm-bindgen", 1214 | "wasm-bindgen-futures", 1215 | "web-sys", 1216 | "yew-macro", 1217 | ] 1218 | 1219 | [[package]] 1220 | name = "yew-macro" 1221 | version = "0.21.0" 1222 | source = "registry+https://github.com/rust-lang/crates.io-index" 1223 | checksum = "02fd8ca5166d69e59f796500a2ce432ff751edecbbb308ca59fd3fe4d0343de2" 1224 | dependencies = [ 1225 | "boolinator", 1226 | "once_cell", 1227 | "prettyplease", 1228 | "proc-macro-error", 1229 | "proc-macro2", 1230 | "quote", 1231 | "syn 2.0.50", 1232 | ] 1233 | 1234 | [[package]] 1235 | name = "yew-websocket" 1236 | version = "1.21.0" 1237 | dependencies = [ 1238 | "anyhow", 1239 | "bincode", 1240 | "futures", 1241 | "gloo 0.8.1", 1242 | "gloo-console 0.2.3", 1243 | "gloo-net 0.2.6", 1244 | "js-sys", 1245 | "rmp-serde", 1246 | "serde", 1247 | "serde_derive", 1248 | "serde_json", 1249 | "thiserror", 1250 | "wasm-bindgen", 1251 | "wasm-bindgen-futures", 1252 | "web-sys", 1253 | "yew", 1254 | ] 1255 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "yew-websocket" 3 | version = "1.21.0" 4 | edition = "2021" 5 | license = "MIT" 6 | description = "Rust yew websocket service written with love :)" 7 | repository = "https://github.com/security-union/yew-websocket.git" 8 | 9 | [dev-dependencies] 10 | bincode = "1" 11 | rmp-serde = "1" 12 | 13 | [dependencies] 14 | yew = "0.21.0" 15 | gloo-net = "0.2" 16 | gloo-console = "0.2" 17 | wasm-bindgen-futures = "0.4" 18 | wasm-bindgen = "0.2" 19 | futures = "0.3" 20 | gloo = { version = "0.8", optional = false } 21 | js-sys = { version = "0.3", optional = false } 22 | thiserror = "1" 23 | anyhow = "1" 24 | serde = "1" 25 | serde_derive = "1" 26 | serde_json = "1" 27 | 28 | [dependencies.web-sys] 29 | version = "0.3" 30 | optional = false 31 | features = [ 32 | "AbortController", 33 | "AbortSignal", 34 | "AnimationEvent", 35 | "BinaryType", 36 | "Blob", 37 | "BlobPropertyBag", 38 | "console", 39 | "DedicatedWorkerGlobalScope", 40 | "Document", 41 | "DomTokenList", 42 | "DragEvent", 43 | "Element", 44 | "ErrorEvent", 45 | "Event", 46 | "EventTarget", 47 | "File", 48 | "FileList", 49 | "FileReader", 50 | "FocusEvent", 51 | "Headers", 52 | "HtmlElement", 53 | "HtmlButtonElement", 54 | "HtmlInputElement", 55 | "HtmlSelectElement", 56 | "HtmlTextAreaElement", 57 | "InputEvent", 58 | "KeyboardEvent", 59 | "Location", 60 | "MessageEvent", 61 | "MouseEvent", 62 | "Node", 63 | "ObserverCallback", 64 | "PointerEvent", 65 | "ProgressEvent", 66 | "ReferrerPolicy", 67 | "Request", 68 | "RequestCache", 69 | "RequestCredentials", 70 | "RequestInit", 71 | "RequestMode", 72 | "RequestRedirect", 73 | "Response", 74 | "Storage", 75 | "Text", 76 | "TouchEvent", 77 | "TransitionEvent", 78 | "UiEvent", 79 | "Url", 80 | "WebSocket", 81 | "WheelEvent", 82 | "Window", 83 | "Worker", 84 | "WorkerGlobalScope", 85 | "WorkerOptions", 86 | ] 87 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Security Union 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Ww0Xt1mAMy31Ofar0GYu8Oab0v2k0uF1XT_zTt5kPU1M8o58sT5OOXCsSxv3nNGxsG8dG4zI=w1060-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj (1)](https://user-images.githubusercontent.com/1176339/155262320-ce1406f0-d35d-418e-a8b9-60b928cceeb2.jpeg) 2 | 3 | # yew-websocket 4 | [![crates.io](https://img.shields.io/crates/v/yew-websocket.svg)](https://crates.io/crates/yew-websocket) 5 | [![docs.rs](https://docs.rs/yew-websocket/badge.svg)](https://docs.rs/yew-websocket) 6 | 7 | Rust yew websocket service written with love :) 8 | 9 | Supports yew version 0.20.0 10 | 11 | This crate is based on the original yew websocket service that used to be part of the core library. 12 | https://github.com/yewstack/yew/blob/0.18.0/packages/yew/src/services/websocket.rs 13 | 14 | For some reason, the core team decided to kill it. 15 | 16 | I tried using the suggested libraries (wasm-sockets or gloo-net), but those are not properly integrated with yew. 17 | 18 | ## Sample 19 | 20 | ```rust 21 | use anyhow::Error; 22 | use serde_derive::{Deserialize, Serialize}; 23 | use yew_websocket::macros::Json; 24 | 25 | use yew::{html, Component, Context, Html}; 26 | use yew_websocket::websocket::{WebSocketService, WebSocketStatus, WebSocketTask}; 27 | 28 | type AsBinary = bool; 29 | 30 | pub enum Format { 31 | Json, 32 | Toml, 33 | } 34 | 35 | pub enum WsAction { 36 | Connect, 37 | SendData(AsBinary), 38 | Disconnect, 39 | Lost, 40 | } 41 | 42 | pub enum Msg { 43 | WsAction(WsAction), 44 | WsReady(Result), 45 | } 46 | 47 | impl From for Msg { 48 | fn from(action: WsAction) -> Self { 49 | Msg::WsAction(action) 50 | } 51 | } 52 | 53 | /// This type is used as a request which sent to websocket connection. 54 | #[derive(Serialize, Debug)] 55 | struct WsRequest { 56 | value: u32, 57 | } 58 | 59 | /// This type is an expected response from a websocket connection. 60 | #[derive(Deserialize, Debug)] 61 | pub struct WsResponse { 62 | value: u32, 63 | } 64 | 65 | pub struct Model { 66 | pub fetching: bool, 67 | pub data: Option, 68 | pub ws: Option, 69 | } 70 | 71 | impl Model { 72 | fn view_data(&self) -> Html { 73 | if let Some(value) = self.data { 74 | html! { 75 |

{ value }

76 | } 77 | } else { 78 | html! { 79 |

{ "Data hasn't fetched yet." }

80 | } 81 | } 82 | } 83 | } 84 | 85 | impl Component for Model { 86 | type Message = Msg; 87 | type Properties = (); 88 | 89 | fn create(ctx: &Context) -> Self { 90 | Self { 91 | fetching: false, 92 | data: None, 93 | ws: None, 94 | } 95 | } 96 | 97 | fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { 98 | match msg { 99 | Msg::WsAction(action) => match action { 100 | WsAction::Connect => { 101 | let callback = ctx.link().callback(|Json(data)| Msg::WsReady(data)); 102 | let notification = ctx.link().batch_callback(|status| match status { 103 | WebSocketStatus::Opened => None, 104 | WebSocketStatus::Closed | WebSocketStatus::Error => { 105 | Some(WsAction::Lost.into()) 106 | } 107 | }); 108 | let task = WebSocketService::connect( 109 | "wss://echo.websocket.events/", 110 | callback, 111 | notification, 112 | ) 113 | .unwrap(); 114 | self.ws = Some(task); 115 | true 116 | } 117 | WsAction::SendData(binary) => { 118 | let request = WsRequest { value: 321 }; 119 | if binary { 120 | self.ws.as_mut().unwrap().send_binary(Json(&request)); 121 | } else { 122 | self.ws.as_mut().unwrap().send(Json(&request)); 123 | } 124 | false 125 | } 126 | WsAction::Disconnect => { 127 | self.ws.take(); 128 | true 129 | } 130 | WsAction::Lost => { 131 | self.ws = None; 132 | true 133 | } 134 | }, 135 | Msg::WsReady(response) => { 136 | self.data = response.map(|data| data.value).ok(); 137 | true 138 | } 139 | } 140 | } 141 | 142 | fn view(&self, ctx: &Context) -> Html { 143 | html! { 144 |
145 | 164 |
165 | } 166 | } 167 | } 168 | 169 | fn main() { 170 | yew::Renderer::::new().render(); 171 | } 172 | ``` 173 | -------------------------------------------------------------------------------- /examples/websocket-demo/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "wasm32-unknown-unknown" 3 | rustflags = [ "--cfg=web_sys_unstable_apis" ] 4 | 5 | [net] 6 | git-fetch-with-cli = true 7 | -------------------------------------------------------------------------------- /examples/websocket-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | dist 3 | -------------------------------------------------------------------------------- /examples/websocket-demo/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 = "anyhow" 22 | version = "1.0.80" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" 25 | 26 | [[package]] 27 | name = "anymap2" 28 | version = "0.13.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" 31 | 32 | [[package]] 33 | name = "autocfg" 34 | version = "1.1.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 37 | 38 | [[package]] 39 | name = "backtrace" 40 | version = "0.3.69" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 43 | dependencies = [ 44 | "addr2line", 45 | "cc", 46 | "cfg-if", 47 | "libc", 48 | "miniz_oxide", 49 | "object", 50 | "rustc-demangle", 51 | ] 52 | 53 | [[package]] 54 | name = "bincode" 55 | version = "1.3.3" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 58 | dependencies = [ 59 | "serde", 60 | ] 61 | 62 | [[package]] 63 | name = "boolinator" 64 | version = "2.4.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" 67 | 68 | [[package]] 69 | name = "bumpalo" 70 | version = "3.15.1" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "c764d619ca78fccbf3069b37bd7af92577f044bb15236036662d79b6559f25b7" 73 | 74 | [[package]] 75 | name = "bytes" 76 | version = "1.5.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" 79 | 80 | [[package]] 81 | name = "cc" 82 | version = "1.0.86" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" 85 | 86 | [[package]] 87 | name = "cfg-if" 88 | version = "1.0.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 91 | 92 | [[package]] 93 | name = "console_error_panic_hook" 94 | version = "0.1.7" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 97 | dependencies = [ 98 | "cfg-if", 99 | "wasm-bindgen", 100 | ] 101 | 102 | [[package]] 103 | name = "equivalent" 104 | version = "1.0.1" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 107 | 108 | [[package]] 109 | name = "fnv" 110 | version = "1.0.7" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 113 | 114 | [[package]] 115 | name = "form_urlencoded" 116 | version = "1.2.1" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 119 | dependencies = [ 120 | "percent-encoding", 121 | ] 122 | 123 | [[package]] 124 | name = "frontend" 125 | version = "0.1.0" 126 | dependencies = [ 127 | "anyhow", 128 | "serde", 129 | "serde_derive", 130 | "serde_json", 131 | "yew", 132 | "yew-websocket", 133 | ] 134 | 135 | [[package]] 136 | name = "futures" 137 | version = "0.3.30" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" 140 | dependencies = [ 141 | "futures-channel", 142 | "futures-core", 143 | "futures-executor", 144 | "futures-io", 145 | "futures-sink", 146 | "futures-task", 147 | "futures-util", 148 | ] 149 | 150 | [[package]] 151 | name = "futures-channel" 152 | version = "0.3.30" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 155 | dependencies = [ 156 | "futures-core", 157 | "futures-sink", 158 | ] 159 | 160 | [[package]] 161 | name = "futures-core" 162 | version = "0.3.30" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 165 | 166 | [[package]] 167 | name = "futures-executor" 168 | version = "0.3.30" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 171 | dependencies = [ 172 | "futures-core", 173 | "futures-task", 174 | "futures-util", 175 | ] 176 | 177 | [[package]] 178 | name = "futures-io" 179 | version = "0.3.30" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 182 | 183 | [[package]] 184 | name = "futures-macro" 185 | version = "0.3.30" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 188 | dependencies = [ 189 | "proc-macro2", 190 | "quote", 191 | "syn 2.0.50", 192 | ] 193 | 194 | [[package]] 195 | name = "futures-sink" 196 | version = "0.3.30" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 199 | 200 | [[package]] 201 | name = "futures-task" 202 | version = "0.3.30" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 205 | 206 | [[package]] 207 | name = "futures-util" 208 | version = "0.3.30" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 211 | dependencies = [ 212 | "futures-channel", 213 | "futures-core", 214 | "futures-io", 215 | "futures-macro", 216 | "futures-sink", 217 | "futures-task", 218 | "memchr", 219 | "pin-project-lite", 220 | "pin-utils", 221 | "slab", 222 | ] 223 | 224 | [[package]] 225 | name = "getrandom" 226 | version = "0.2.12" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" 229 | dependencies = [ 230 | "cfg-if", 231 | "js-sys", 232 | "libc", 233 | "wasi", 234 | "wasm-bindgen", 235 | ] 236 | 237 | [[package]] 238 | name = "gimli" 239 | version = "0.28.1" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 242 | 243 | [[package]] 244 | name = "gloo" 245 | version = "0.8.1" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "28999cda5ef6916ffd33fb4a7b87e1de633c47c0dc6d97905fee1cdaa142b94d" 248 | dependencies = [ 249 | "gloo-console 0.2.3", 250 | "gloo-dialogs 0.1.1", 251 | "gloo-events 0.1.2", 252 | "gloo-file 0.2.3", 253 | "gloo-history 0.1.5", 254 | "gloo-net 0.3.1", 255 | "gloo-render 0.1.1", 256 | "gloo-storage 0.2.2", 257 | "gloo-timers 0.2.6", 258 | "gloo-utils 0.1.7", 259 | "gloo-worker 0.2.1", 260 | ] 261 | 262 | [[package]] 263 | name = "gloo" 264 | version = "0.10.0" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "cd35526c28cc55c1db77aed6296de58677dbab863b118483a27845631d870249" 267 | dependencies = [ 268 | "gloo-console 0.3.0", 269 | "gloo-dialogs 0.2.0", 270 | "gloo-events 0.2.0", 271 | "gloo-file 0.3.0", 272 | "gloo-history 0.2.2", 273 | "gloo-net 0.4.0", 274 | "gloo-render 0.2.0", 275 | "gloo-storage 0.3.0", 276 | "gloo-timers 0.3.0", 277 | "gloo-utils 0.2.0", 278 | "gloo-worker 0.4.0", 279 | ] 280 | 281 | [[package]] 282 | name = "gloo-console" 283 | version = "0.2.3" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" 286 | dependencies = [ 287 | "gloo-utils 0.1.7", 288 | "js-sys", 289 | "serde", 290 | "wasm-bindgen", 291 | "web-sys", 292 | ] 293 | 294 | [[package]] 295 | name = "gloo-console" 296 | version = "0.3.0" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261" 299 | dependencies = [ 300 | "gloo-utils 0.2.0", 301 | "js-sys", 302 | "serde", 303 | "wasm-bindgen", 304 | "web-sys", 305 | ] 306 | 307 | [[package]] 308 | name = "gloo-dialogs" 309 | version = "0.1.1" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6" 312 | dependencies = [ 313 | "wasm-bindgen", 314 | "web-sys", 315 | ] 316 | 317 | [[package]] 318 | name = "gloo-dialogs" 319 | version = "0.2.0" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "bf4748e10122b01435750ff530095b1217cf6546173459448b83913ebe7815df" 322 | dependencies = [ 323 | "wasm-bindgen", 324 | "web-sys", 325 | ] 326 | 327 | [[package]] 328 | name = "gloo-events" 329 | version = "0.1.2" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc" 332 | dependencies = [ 333 | "wasm-bindgen", 334 | "web-sys", 335 | ] 336 | 337 | [[package]] 338 | name = "gloo-events" 339 | version = "0.2.0" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "27c26fb45f7c385ba980f5fa87ac677e363949e065a083722697ef1b2cc91e41" 342 | dependencies = [ 343 | "wasm-bindgen", 344 | "web-sys", 345 | ] 346 | 347 | [[package]] 348 | name = "gloo-file" 349 | version = "0.2.3" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" 352 | dependencies = [ 353 | "gloo-events 0.1.2", 354 | "js-sys", 355 | "wasm-bindgen", 356 | "web-sys", 357 | ] 358 | 359 | [[package]] 360 | name = "gloo-file" 361 | version = "0.3.0" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f" 364 | dependencies = [ 365 | "gloo-events 0.2.0", 366 | "js-sys", 367 | "wasm-bindgen", 368 | "web-sys", 369 | ] 370 | 371 | [[package]] 372 | name = "gloo-history" 373 | version = "0.1.5" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f" 376 | dependencies = [ 377 | "gloo-events 0.1.2", 378 | "gloo-utils 0.1.7", 379 | "serde", 380 | "serde-wasm-bindgen 0.5.0", 381 | "serde_urlencoded", 382 | "thiserror", 383 | "wasm-bindgen", 384 | "web-sys", 385 | ] 386 | 387 | [[package]] 388 | name = "gloo-history" 389 | version = "0.2.2" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "903f432be5ba34427eac5e16048ef65604a82061fe93789f2212afc73d8617d6" 392 | dependencies = [ 393 | "getrandom", 394 | "gloo-events 0.2.0", 395 | "gloo-utils 0.2.0", 396 | "serde", 397 | "serde-wasm-bindgen 0.6.3", 398 | "serde_urlencoded", 399 | "thiserror", 400 | "wasm-bindgen", 401 | "web-sys", 402 | ] 403 | 404 | [[package]] 405 | name = "gloo-net" 406 | version = "0.2.6" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10" 409 | dependencies = [ 410 | "futures-channel", 411 | "futures-core", 412 | "futures-sink", 413 | "gloo-utils 0.1.7", 414 | "js-sys", 415 | "pin-project", 416 | "serde", 417 | "serde_json", 418 | "thiserror", 419 | "wasm-bindgen", 420 | "wasm-bindgen-futures", 421 | "web-sys", 422 | ] 423 | 424 | [[package]] 425 | name = "gloo-net" 426 | version = "0.3.1" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620" 429 | dependencies = [ 430 | "futures-channel", 431 | "futures-core", 432 | "futures-sink", 433 | "gloo-utils 0.1.7", 434 | "http", 435 | "js-sys", 436 | "pin-project", 437 | "serde", 438 | "serde_json", 439 | "thiserror", 440 | "wasm-bindgen", 441 | "wasm-bindgen-futures", 442 | "web-sys", 443 | ] 444 | 445 | [[package]] 446 | name = "gloo-net" 447 | version = "0.4.0" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "8ac9e8288ae2c632fa9f8657ac70bfe38a1530f345282d7ba66a1f70b72b7dc4" 450 | dependencies = [ 451 | "futures-channel", 452 | "futures-core", 453 | "futures-sink", 454 | "gloo-utils 0.2.0", 455 | "http", 456 | "js-sys", 457 | "pin-project", 458 | "serde", 459 | "serde_json", 460 | "thiserror", 461 | "wasm-bindgen", 462 | "wasm-bindgen-futures", 463 | "web-sys", 464 | ] 465 | 466 | [[package]] 467 | name = "gloo-render" 468 | version = "0.1.1" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764" 471 | dependencies = [ 472 | "wasm-bindgen", 473 | "web-sys", 474 | ] 475 | 476 | [[package]] 477 | name = "gloo-render" 478 | version = "0.2.0" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "56008b6744713a8e8d98ac3dcb7d06543d5662358c9c805b4ce2167ad4649833" 481 | dependencies = [ 482 | "wasm-bindgen", 483 | "web-sys", 484 | ] 485 | 486 | [[package]] 487 | name = "gloo-storage" 488 | version = "0.2.2" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" 491 | dependencies = [ 492 | "gloo-utils 0.1.7", 493 | "js-sys", 494 | "serde", 495 | "serde_json", 496 | "thiserror", 497 | "wasm-bindgen", 498 | "web-sys", 499 | ] 500 | 501 | [[package]] 502 | name = "gloo-storage" 503 | version = "0.3.0" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" 506 | dependencies = [ 507 | "gloo-utils 0.2.0", 508 | "js-sys", 509 | "serde", 510 | "serde_json", 511 | "thiserror", 512 | "wasm-bindgen", 513 | "web-sys", 514 | ] 515 | 516 | [[package]] 517 | name = "gloo-timers" 518 | version = "0.2.6" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" 521 | dependencies = [ 522 | "js-sys", 523 | "wasm-bindgen", 524 | ] 525 | 526 | [[package]] 527 | name = "gloo-timers" 528 | version = "0.3.0" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" 531 | dependencies = [ 532 | "js-sys", 533 | "wasm-bindgen", 534 | ] 535 | 536 | [[package]] 537 | name = "gloo-utils" 538 | version = "0.1.7" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" 541 | dependencies = [ 542 | "js-sys", 543 | "serde", 544 | "serde_json", 545 | "wasm-bindgen", 546 | "web-sys", 547 | ] 548 | 549 | [[package]] 550 | name = "gloo-utils" 551 | version = "0.2.0" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" 554 | dependencies = [ 555 | "js-sys", 556 | "serde", 557 | "serde_json", 558 | "wasm-bindgen", 559 | "web-sys", 560 | ] 561 | 562 | [[package]] 563 | name = "gloo-worker" 564 | version = "0.2.1" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a" 567 | dependencies = [ 568 | "anymap2", 569 | "bincode", 570 | "gloo-console 0.2.3", 571 | "gloo-utils 0.1.7", 572 | "js-sys", 573 | "serde", 574 | "wasm-bindgen", 575 | "wasm-bindgen-futures", 576 | "web-sys", 577 | ] 578 | 579 | [[package]] 580 | name = "gloo-worker" 581 | version = "0.4.0" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "76495d3dd87de51da268fa3a593da118ab43eb7f8809e17eb38d3319b424e400" 584 | dependencies = [ 585 | "bincode", 586 | "futures", 587 | "gloo-utils 0.2.0", 588 | "gloo-worker-macros", 589 | "js-sys", 590 | "pinned", 591 | "serde", 592 | "thiserror", 593 | "wasm-bindgen", 594 | "wasm-bindgen-futures", 595 | "web-sys", 596 | ] 597 | 598 | [[package]] 599 | name = "gloo-worker-macros" 600 | version = "0.1.0" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | checksum = "956caa58d4857bc9941749d55e4bd3000032d8212762586fa5705632967140e7" 603 | dependencies = [ 604 | "proc-macro-crate", 605 | "proc-macro2", 606 | "quote", 607 | "syn 2.0.50", 608 | ] 609 | 610 | [[package]] 611 | name = "hashbrown" 612 | version = "0.14.3" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" 615 | 616 | [[package]] 617 | name = "hermit-abi" 618 | version = "0.3.6" 619 | source = "registry+https://github.com/rust-lang/crates.io-index" 620 | checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" 621 | 622 | [[package]] 623 | name = "http" 624 | version = "0.2.11" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" 627 | dependencies = [ 628 | "bytes", 629 | "fnv", 630 | "itoa", 631 | ] 632 | 633 | [[package]] 634 | name = "implicit-clone" 635 | version = "0.4.8" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "fc06a255cbf402a52ae399c05a518c68c569c916ea11423620111df576b9b9bb" 638 | dependencies = [ 639 | "implicit-clone-derive", 640 | "indexmap", 641 | ] 642 | 643 | [[package]] 644 | name = "implicit-clone-derive" 645 | version = "0.1.1" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "9311685eb9a34808bbb0608ad2fcab9ae216266beca5848613e95553ac914e3b" 648 | dependencies = [ 649 | "quote", 650 | "syn 2.0.50", 651 | ] 652 | 653 | [[package]] 654 | name = "indexmap" 655 | version = "2.2.3" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" 658 | dependencies = [ 659 | "equivalent", 660 | "hashbrown", 661 | ] 662 | 663 | [[package]] 664 | name = "itoa" 665 | version = "1.0.10" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" 668 | 669 | [[package]] 670 | name = "js-sys" 671 | version = "0.3.68" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" 674 | dependencies = [ 675 | "wasm-bindgen", 676 | ] 677 | 678 | [[package]] 679 | name = "libc" 680 | version = "0.2.153" 681 | source = "registry+https://github.com/rust-lang/crates.io-index" 682 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 683 | 684 | [[package]] 685 | name = "log" 686 | version = "0.4.20" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 689 | 690 | [[package]] 691 | name = "memchr" 692 | version = "2.7.1" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" 695 | 696 | [[package]] 697 | name = "miniz_oxide" 698 | version = "0.7.2" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 701 | dependencies = [ 702 | "adler", 703 | ] 704 | 705 | [[package]] 706 | name = "num_cpus" 707 | version = "1.16.0" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 710 | dependencies = [ 711 | "hermit-abi", 712 | "libc", 713 | ] 714 | 715 | [[package]] 716 | name = "object" 717 | version = "0.32.2" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 720 | dependencies = [ 721 | "memchr", 722 | ] 723 | 724 | [[package]] 725 | name = "once_cell" 726 | version = "1.19.0" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 729 | 730 | [[package]] 731 | name = "percent-encoding" 732 | version = "2.3.1" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 735 | 736 | [[package]] 737 | name = "pin-project" 738 | version = "1.1.4" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" 741 | dependencies = [ 742 | "pin-project-internal", 743 | ] 744 | 745 | [[package]] 746 | name = "pin-project-internal" 747 | version = "1.1.4" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" 750 | dependencies = [ 751 | "proc-macro2", 752 | "quote", 753 | "syn 2.0.50", 754 | ] 755 | 756 | [[package]] 757 | name = "pin-project-lite" 758 | version = "0.2.13" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" 761 | 762 | [[package]] 763 | name = "pin-utils" 764 | version = "0.1.0" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 767 | 768 | [[package]] 769 | name = "pinned" 770 | version = "0.1.0" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b" 773 | dependencies = [ 774 | "futures", 775 | "rustversion", 776 | "thiserror", 777 | ] 778 | 779 | [[package]] 780 | name = "prettyplease" 781 | version = "0.2.16" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" 784 | dependencies = [ 785 | "proc-macro2", 786 | "syn 2.0.50", 787 | ] 788 | 789 | [[package]] 790 | name = "proc-macro-crate" 791 | version = "1.3.1" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" 794 | dependencies = [ 795 | "once_cell", 796 | "toml_edit", 797 | ] 798 | 799 | [[package]] 800 | name = "proc-macro-error" 801 | version = "1.0.4" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 804 | dependencies = [ 805 | "proc-macro-error-attr", 806 | "proc-macro2", 807 | "quote", 808 | "syn 1.0.109", 809 | "version_check", 810 | ] 811 | 812 | [[package]] 813 | name = "proc-macro-error-attr" 814 | version = "1.0.4" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 817 | dependencies = [ 818 | "proc-macro2", 819 | "quote", 820 | "version_check", 821 | ] 822 | 823 | [[package]] 824 | name = "proc-macro2" 825 | version = "1.0.78" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" 828 | dependencies = [ 829 | "unicode-ident", 830 | ] 831 | 832 | [[package]] 833 | name = "prokio" 834 | version = "0.1.0" 835 | source = "registry+https://github.com/rust-lang/crates.io-index" 836 | checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488" 837 | dependencies = [ 838 | "futures", 839 | "gloo 0.8.1", 840 | "num_cpus", 841 | "once_cell", 842 | "pin-project", 843 | "pinned", 844 | "tokio", 845 | "tokio-stream", 846 | "wasm-bindgen-futures", 847 | ] 848 | 849 | [[package]] 850 | name = "quote" 851 | version = "1.0.35" 852 | source = "registry+https://github.com/rust-lang/crates.io-index" 853 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 854 | dependencies = [ 855 | "proc-macro2", 856 | ] 857 | 858 | [[package]] 859 | name = "rustc-demangle" 860 | version = "0.1.23" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 863 | 864 | [[package]] 865 | name = "rustversion" 866 | version = "1.0.14" 867 | source = "registry+https://github.com/rust-lang/crates.io-index" 868 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" 869 | 870 | [[package]] 871 | name = "ryu" 872 | version = "1.0.17" 873 | source = "registry+https://github.com/rust-lang/crates.io-index" 874 | checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" 875 | 876 | [[package]] 877 | name = "serde" 878 | version = "1.0.197" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" 881 | dependencies = [ 882 | "serde_derive", 883 | ] 884 | 885 | [[package]] 886 | name = "serde-wasm-bindgen" 887 | version = "0.5.0" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" 890 | dependencies = [ 891 | "js-sys", 892 | "serde", 893 | "wasm-bindgen", 894 | ] 895 | 896 | [[package]] 897 | name = "serde-wasm-bindgen" 898 | version = "0.6.3" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "b9b713f70513ae1f8d92665bbbbda5c295c2cf1da5542881ae5eefe20c9af132" 901 | dependencies = [ 902 | "js-sys", 903 | "serde", 904 | "wasm-bindgen", 905 | ] 906 | 907 | [[package]] 908 | name = "serde_derive" 909 | version = "1.0.197" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" 912 | dependencies = [ 913 | "proc-macro2", 914 | "quote", 915 | "syn 2.0.50", 916 | ] 917 | 918 | [[package]] 919 | name = "serde_json" 920 | version = "1.0.114" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" 923 | dependencies = [ 924 | "itoa", 925 | "ryu", 926 | "serde", 927 | ] 928 | 929 | [[package]] 930 | name = "serde_urlencoded" 931 | version = "0.7.1" 932 | source = "registry+https://github.com/rust-lang/crates.io-index" 933 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 934 | dependencies = [ 935 | "form_urlencoded", 936 | "itoa", 937 | "ryu", 938 | "serde", 939 | ] 940 | 941 | [[package]] 942 | name = "slab" 943 | version = "0.4.9" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 946 | dependencies = [ 947 | "autocfg", 948 | ] 949 | 950 | [[package]] 951 | name = "syn" 952 | version = "1.0.109" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 955 | dependencies = [ 956 | "proc-macro2", 957 | "unicode-ident", 958 | ] 959 | 960 | [[package]] 961 | name = "syn" 962 | version = "2.0.50" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" 965 | dependencies = [ 966 | "proc-macro2", 967 | "quote", 968 | "unicode-ident", 969 | ] 970 | 971 | [[package]] 972 | name = "thiserror" 973 | version = "1.0.57" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" 976 | dependencies = [ 977 | "thiserror-impl", 978 | ] 979 | 980 | [[package]] 981 | name = "thiserror-impl" 982 | version = "1.0.57" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" 985 | dependencies = [ 986 | "proc-macro2", 987 | "quote", 988 | "syn 2.0.50", 989 | ] 990 | 991 | [[package]] 992 | name = "tokio" 993 | version = "1.36.0" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" 996 | dependencies = [ 997 | "backtrace", 998 | "pin-project-lite", 999 | ] 1000 | 1001 | [[package]] 1002 | name = "tokio-stream" 1003 | version = "0.1.14" 1004 | source = "registry+https://github.com/rust-lang/crates.io-index" 1005 | checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" 1006 | dependencies = [ 1007 | "futures-core", 1008 | "pin-project-lite", 1009 | "tokio", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "toml_datetime" 1014 | version = "0.6.5" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" 1017 | 1018 | [[package]] 1019 | name = "toml_edit" 1020 | version = "0.19.15" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" 1023 | dependencies = [ 1024 | "indexmap", 1025 | "toml_datetime", 1026 | "winnow", 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "tracing" 1031 | version = "0.1.40" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1034 | dependencies = [ 1035 | "pin-project-lite", 1036 | "tracing-attributes", 1037 | "tracing-core", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "tracing-attributes" 1042 | version = "0.1.27" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 1045 | dependencies = [ 1046 | "proc-macro2", 1047 | "quote", 1048 | "syn 2.0.50", 1049 | ] 1050 | 1051 | [[package]] 1052 | name = "tracing-core" 1053 | version = "0.1.32" 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" 1055 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1056 | dependencies = [ 1057 | "once_cell", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "unicode-ident" 1062 | version = "1.0.12" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1065 | 1066 | [[package]] 1067 | name = "version_check" 1068 | version = "0.9.4" 1069 | source = "registry+https://github.com/rust-lang/crates.io-index" 1070 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1071 | 1072 | [[package]] 1073 | name = "wasi" 1074 | version = "0.11.0+wasi-snapshot-preview1" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1077 | 1078 | [[package]] 1079 | name = "wasm-bindgen" 1080 | version = "0.2.91" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" 1083 | dependencies = [ 1084 | "cfg-if", 1085 | "wasm-bindgen-macro", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "wasm-bindgen-backend" 1090 | version = "0.2.91" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" 1093 | dependencies = [ 1094 | "bumpalo", 1095 | "log", 1096 | "once_cell", 1097 | "proc-macro2", 1098 | "quote", 1099 | "syn 2.0.50", 1100 | "wasm-bindgen-shared", 1101 | ] 1102 | 1103 | [[package]] 1104 | name = "wasm-bindgen-futures" 1105 | version = "0.4.41" 1106 | source = "registry+https://github.com/rust-lang/crates.io-index" 1107 | checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" 1108 | dependencies = [ 1109 | "cfg-if", 1110 | "js-sys", 1111 | "wasm-bindgen", 1112 | "web-sys", 1113 | ] 1114 | 1115 | [[package]] 1116 | name = "wasm-bindgen-macro" 1117 | version = "0.2.91" 1118 | source = "registry+https://github.com/rust-lang/crates.io-index" 1119 | checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" 1120 | dependencies = [ 1121 | "quote", 1122 | "wasm-bindgen-macro-support", 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "wasm-bindgen-macro-support" 1127 | version = "0.2.91" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" 1130 | dependencies = [ 1131 | "proc-macro2", 1132 | "quote", 1133 | "syn 2.0.50", 1134 | "wasm-bindgen-backend", 1135 | "wasm-bindgen-shared", 1136 | ] 1137 | 1138 | [[package]] 1139 | name = "wasm-bindgen-shared" 1140 | version = "0.2.91" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" 1143 | 1144 | [[package]] 1145 | name = "web-sys" 1146 | version = "0.3.68" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" 1149 | dependencies = [ 1150 | "js-sys", 1151 | "wasm-bindgen", 1152 | ] 1153 | 1154 | [[package]] 1155 | name = "winnow" 1156 | version = "0.5.40" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 1159 | dependencies = [ 1160 | "memchr", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "yew" 1165 | version = "0.21.0" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "5f1a03f255c70c7aa3e9c62e15292f142ede0564123543c1cc0c7a4f31660cac" 1168 | dependencies = [ 1169 | "console_error_panic_hook", 1170 | "futures", 1171 | "gloo 0.10.0", 1172 | "implicit-clone", 1173 | "indexmap", 1174 | "js-sys", 1175 | "prokio", 1176 | "rustversion", 1177 | "serde", 1178 | "slab", 1179 | "thiserror", 1180 | "tokio", 1181 | "tracing", 1182 | "wasm-bindgen", 1183 | "wasm-bindgen-futures", 1184 | "web-sys", 1185 | "yew-macro", 1186 | ] 1187 | 1188 | [[package]] 1189 | name = "yew-macro" 1190 | version = "0.21.0" 1191 | source = "registry+https://github.com/rust-lang/crates.io-index" 1192 | checksum = "02fd8ca5166d69e59f796500a2ce432ff751edecbbb308ca59fd3fe4d0343de2" 1193 | dependencies = [ 1194 | "boolinator", 1195 | "once_cell", 1196 | "prettyplease", 1197 | "proc-macro-error", 1198 | "proc-macro2", 1199 | "quote", 1200 | "syn 2.0.50", 1201 | ] 1202 | 1203 | [[package]] 1204 | name = "yew-websocket" 1205 | version = "0.21.0" 1206 | dependencies = [ 1207 | "anyhow", 1208 | "futures", 1209 | "gloo 0.8.1", 1210 | "gloo-console 0.2.3", 1211 | "gloo-net 0.2.6", 1212 | "js-sys", 1213 | "serde", 1214 | "serde_derive", 1215 | "serde_json", 1216 | "thiserror", 1217 | "wasm-bindgen", 1218 | "wasm-bindgen-futures", 1219 | "web-sys", 1220 | "yew", 1221 | ] 1222 | -------------------------------------------------------------------------------- /examples/websocket-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "frontend" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | yew = { version = "0.21.0", features = ["csr"] } 8 | anyhow = "1" 9 | serde = "1" 10 | serde_derive = "1" 11 | serde_json = "1" 12 | yew-websocket = { path = "../../"} 13 | -------------------------------------------------------------------------------- /examples/websocket-demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Video Streaming 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/websocket-demo/src/macros/mod.rs: -------------------------------------------------------------------------------- 1 | //! Contains three macros for wrapping serde format. Collectively they 2 | //! allow you to define your own text and binary wrappers. 3 | 4 | use yew_websocket::websocket::{Binary, Text}; 5 | 6 | /** 7 | * Copyright (c) 2017 Denis Kolodin 8 | Permission is hereby granted, free of charge, to any 9 | person obtaining a copy of this software and associated 10 | documentation files (the "Software"), to deal in the 11 | Software without restriction, including without 12 | limitation the rights to use, copy, modify, merge, 13 | publish, distribute, sublicense, and/or sell copies of 14 | the Software, and to permit persons to whom the Software 15 | is furnished to do so, subject to the following 16 | conditions: 17 | The above copyright notice and this permission notice 18 | shall be included in all copies or substantial portions 19 | of the Software. 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 21 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 22 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 23 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 24 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 27 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | /// This macro is used for a format that can be encoded as Text. It 32 | /// is used in conjunction with a type definition for a tuple struct 33 | /// with one (publically accessible) element of a generic type. Since 34 | /// any type that can be encoded as Text can also be encoded as Binary, 35 | /// it should be used with the binary_format macro. 36 | /// 37 | /// ## Example 38 | /// 39 | /// ```rust 40 | /// use yew_websocket::{binary_format, text_format}; 41 | /// 42 | /// pub struct Json(pub T); 43 | /// 44 | /// text_format!(Json based on serde_json); 45 | /// binary_format!(Json based on serde_json); 46 | /// ``` 47 | #[macro_export] 48 | macro_rules! text_format { 49 | ($type:ident based on $format:ident) => { 50 | impl From for $type> 51 | where 52 | T: for<'de> ::serde::Deserialize<'de>, 53 | { 54 | fn from(value: Text) -> Self { 55 | match value { 56 | Ok(data) => $type($format::from_str(&data).map_err(::anyhow::Error::from)), 57 | Err(reason) => $type(Err(reason)), 58 | } 59 | } 60 | } 61 | }; 62 | } 63 | 64 | /// This macro is used for a format that can be encoded as Binary. It 65 | /// is used in conjunction with a type definition for a tuple struct 66 | /// with one (publicly accessible) element of a generic type. Not 67 | /// all types that can be encoded as Binary can be encoded as Text. 68 | /// As such, this macro should be paired with the text_format macro 69 | /// where such an encoding works (e.g., JSON), or with the 70 | /// text_format_is_an_error macro for binary-only formats (e.g., 71 | /// MsgPack). 72 | /// 73 | /// # Rely on serde's `to_vec` and `from_vec` 74 | /// The simplest form of this macro relegates all the work to serde's 75 | /// `to_vec` function for serialization and serde's `from_vec` for 76 | /// deseriaization. 77 | /// 78 | /// ## Examples 79 | /// 80 | /// ### Binary that is also Text 81 | /// 82 | /// ```rust 83 | /// use yew_websocket::{binary_format, text_format}; 84 | /// 85 | /// pub struct Json(pub T); 86 | /// 87 | /// text_format!(Json based on serde_json); 88 | /// binary_format!(Json based on serde_json); 89 | /// ``` 90 | /// 91 | /// ### Binary only 92 | /// ```rust 93 | /// # mod to_make_rustdoc_happy { 94 | /// use rmp_serde; 95 | /// use yew_websocket::binary_format; 96 | /// 97 | /// pub struct MsgPack(pub T); 98 | /// 99 | /// binary_format!(MsgPack based on rmp_serde); 100 | /// # } 101 | /// ``` 102 | /// 103 | /// # Supply serialization and deserialization functions 104 | /// 105 | /// In addition to the "based on" form of this macro demonstrated above, 106 | /// you can use the three parameter second form to supply 107 | /// non-standard (i.e., alternatives to serde's `to_vec` and/or `from_slice`) 108 | /// helpers as the second and third parameters. 109 | /// 110 | /// ## Example 111 | /// ```rust 112 | /// # mod to_make_rustdoc_happy { 113 | /// use bincode; 114 | /// use yew_websocket::binary_format; 115 | /// 116 | /// pub struct Bincode(pub T); 117 | /// 118 | /// binary_format!(Bincode, bincode::serialize, bincode::deserialize); 119 | /// # } 120 | /// ``` 121 | #[macro_export] 122 | macro_rules! binary_format { 123 | ($type:ident based on $format:ident) => { 124 | binary_format!($type, $format::from_slice); 125 | }; 126 | ($type:ident, $from:path) => { 127 | impl From for $type> 128 | where 129 | T: for<'de> ::serde::Deserialize<'de>, 130 | { 131 | fn from(value: Binary) -> Self { 132 | match value { 133 | Ok(data) => $type($from(&data).map_err(::anyhow::Error::from)), 134 | Err(reason) => $type(Err(reason)), 135 | } 136 | } 137 | } 138 | }; 139 | } 140 | 141 | #[derive(Debug)] 142 | pub struct Json(pub T); 143 | 144 | text_format!(Json based on serde_json); 145 | 146 | binary_format!(Json based on serde_json); 147 | -------------------------------------------------------------------------------- /examples/websocket-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Error; 2 | use macros::Json; 3 | use serde_derive::{Deserialize, Serialize}; 4 | 5 | use yew::{html, Component, Context, Html}; 6 | use yew_websocket::websocket::{WebSocketService, WebSocketStatus, WebSocketTask}; 7 | 8 | pub mod macros; 9 | 10 | type AsBinary = bool; 11 | 12 | pub enum Format { 13 | Json, 14 | Toml, 15 | } 16 | 17 | pub enum WsAction { 18 | Connect, 19 | SendData(AsBinary), 20 | Disconnect, 21 | Lost, 22 | } 23 | 24 | pub enum Msg { 25 | WsAction(WsAction), 26 | WsReady(Result), 27 | } 28 | 29 | impl From for Msg { 30 | fn from(action: WsAction) -> Self { 31 | Msg::WsAction(action) 32 | } 33 | } 34 | 35 | /// This type is used as a request which sent to websocket connection. 36 | #[derive(Serialize, Debug)] 37 | struct WsRequest { 38 | value: u32, 39 | } 40 | 41 | /// This type is an expected response from a websocket connection. 42 | #[derive(Deserialize, Debug)] 43 | pub struct WsResponse { 44 | value: u32, 45 | } 46 | 47 | pub struct Model { 48 | pub fetching: bool, 49 | pub data: Option, 50 | pub ws: Option, 51 | } 52 | 53 | impl Model { 54 | fn view_data(&self) -> Html { 55 | if let Some(value) = self.data { 56 | html! { 57 |

{ value }

58 | } 59 | } else { 60 | html! { 61 |

{ "Data hasn't fetched yet." }

62 | } 63 | } 64 | } 65 | } 66 | 67 | impl Component for Model { 68 | type Message = Msg; 69 | type Properties = (); 70 | 71 | fn create(_ctx: &Context) -> Self { 72 | Self { 73 | fetching: false, 74 | data: None, 75 | ws: None, 76 | } 77 | } 78 | 79 | fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { 80 | match msg { 81 | Msg::WsAction(action) => match action { 82 | WsAction::Connect => { 83 | let callback = ctx.link().callback(|Json(data)| Msg::WsReady(data)); 84 | let notification = ctx.link().batch_callback(|status| match status { 85 | WebSocketStatus::Opened => None, 86 | WebSocketStatus::Closed | WebSocketStatus::Error => { 87 | Some(WsAction::Lost.into()) 88 | } 89 | }); 90 | let task = WebSocketService::connect( 91 | "wss://echo.websocket.events/", 92 | callback, 93 | notification, 94 | ) 95 | .unwrap(); 96 | self.ws = Some(task); 97 | true 98 | } 99 | WsAction::SendData(binary) => { 100 | let request = WsRequest { value: 321 }; 101 | if binary { 102 | self.ws 103 | .as_mut() 104 | .unwrap() 105 | .send_binary(serde_json::to_string(&request).unwrap().into_bytes()); 106 | } else { 107 | self.ws 108 | .as_mut() 109 | .unwrap() 110 | .send(serde_json::to_string(&request).unwrap()); 111 | } 112 | false 113 | } 114 | WsAction::Disconnect => { 115 | self.ws.take(); 116 | true 117 | } 118 | WsAction::Lost => { 119 | self.ws = None; 120 | true 121 | } 122 | }, 123 | Msg::WsReady(response) => { 124 | self.data = response.map(|data| data.value).ok(); 125 | true 126 | } 127 | } 128 | } 129 | 130 | fn view(&self, ctx: &Context) -> Html { 131 | html! { 132 |
133 | 152 |
153 | } 154 | } 155 | } 156 | 157 | fn main() { 158 | yew::Renderer::::new().render(); 159 | } 160 | -------------------------------------------------------------------------------- /src/format.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Error; 2 | 3 | /** 4 | * Copyright (c) 2017 Denis Kolodin 5 | 6 | Permission is hereby granted, free of charge, to any 7 | person obtaining a copy of this software and associated 8 | documentation files (the "Software"), to deal in the 9 | Software without restriction, including without 10 | limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of 12 | the Software, and to permit persons to whom the Software 13 | is furnished to do so, subject to the following 14 | conditions: 15 | 16 | The above copyright notice and this permission notice 17 | shall be included in all copies or substantial portions 18 | of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 21 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 22 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 23 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 24 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 27 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | /// A representation of a value which can be stored and restored as a text. 32 | /// 33 | /// Some formats are binary only and can't be serialized to or deserialized 34 | /// from Text. Attempting to do so will return an Err(FormatError). 35 | pub type Text = Result; 36 | 37 | /// A representation of a value which can be stored and restored as a binary. 38 | pub type Binary = Result, Error>; 39 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod format; 2 | pub mod websocket; 3 | -------------------------------------------------------------------------------- /src/websocket.rs: -------------------------------------------------------------------------------- 1 | //! A service to connect to a server through the 2 | //! [`WebSocket` Protocol](https://tools.ietf.org/html/rfc6455). 3 | 4 | /** 5 | * Copyright (c) 2017 Denis Kolodin 6 | 7 | Permission is hereby granted, free of charge, to any 8 | person obtaining a copy of this software and associated 9 | documentation files (the "Software"), to deal in the 10 | Software without restriction, including without 11 | limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of 13 | the Software, and to permit persons to whom the Software 14 | is furnished to do so, subject to the following 15 | conditions: 16 | 17 | The above copyright notice and this permission notice 18 | shall be included in all copies or substantial portions 19 | of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 22 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 23 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 24 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 25 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 28 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 | DEALINGS IN THE SOFTWARE. 30 | */ 31 | use anyhow::Error; 32 | use std::fmt; 33 | use thiserror::Error as ThisError; 34 | use yew::callback::Callback; 35 | 36 | use gloo::events::EventListener; 37 | use js_sys::Uint8Array; 38 | use wasm_bindgen::JsCast; 39 | use web_sys::{BinaryType, Event, MessageEvent, WebSocket}; 40 | 41 | /// Represents formatting errors. 42 | #[derive(Debug, ThisError)] 43 | pub enum FormatError { 44 | /// Received text for a binary format, e.g. someone sending text 45 | /// on a WebSocket that is using a binary serialization format, like Cbor. 46 | #[error("received text for a binary format")] 47 | ReceivedTextForBinary, 48 | /// Received binary for a text format, e.g. someone sending binary 49 | /// on a WebSocket that is using a text serialization format, like Json. 50 | #[error("received binary for a text format")] 51 | ReceivedBinaryForText, 52 | /// Trying to encode a binary format as text", e.g., trying to 53 | /// store a Cbor encoded value in a String. 54 | #[error("trying to encode a binary format as Text")] 55 | CantEncodeBinaryAsText, 56 | } 57 | 58 | /// A representation of a value which can be stored and restored as a text. 59 | /// 60 | /// Some formats are binary only and can't be serialized to or deserialized 61 | /// from Text. Attempting to do so will return an Err(FormatError). 62 | pub type Text = Result; 63 | 64 | /// A representation of a value which can be stored and restored as a binary. 65 | pub type Binary = Result, Error>; 66 | 67 | /// The status of a WebSocket connection. Used for status notifications. 68 | #[derive(Clone, Debug, PartialEq)] 69 | pub enum WebSocketStatus { 70 | /// Fired when a WebSocket connection has opened. 71 | Opened, 72 | /// Fired when a WebSocket connection has closed. 73 | Closed, 74 | /// Fired when a WebSocket connection has failed. 75 | Error, 76 | } 77 | 78 | #[derive(Clone, Debug, PartialEq, thiserror::Error)] 79 | /// An error encountered by a WebSocket. 80 | pub enum WebSocketError { 81 | #[error("{0}")] 82 | /// An error encountered when creating the WebSocket. 83 | CreationError(String), 84 | } 85 | 86 | /// A handle to control the WebSocket connection. Implements `Task` and could be canceled. 87 | #[must_use = "the connection will be closed when the task is dropped"] 88 | pub struct WebSocketTask { 89 | ws: WebSocket, 90 | notification: Callback, 91 | #[allow(dead_code)] 92 | listeners: [EventListener; 4], 93 | } 94 | 95 | impl WebSocketTask { 96 | fn new( 97 | ws: WebSocket, 98 | notification: Callback, 99 | listener_0: EventListener, 100 | listeners: [EventListener; 3], 101 | ) -> WebSocketTask { 102 | let [listener_1, listener_2, listener_3] = listeners; 103 | WebSocketTask { 104 | ws, 105 | notification, 106 | listeners: [listener_0, listener_1, listener_2, listener_3], 107 | } 108 | } 109 | } 110 | 111 | impl fmt::Debug for WebSocketTask { 112 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 113 | f.write_str("WebSocketTask") 114 | } 115 | } 116 | 117 | /// A WebSocket service attached to a user context. 118 | #[derive(Default, Debug)] 119 | pub struct WebSocketService {} 120 | 121 | impl WebSocketService { 122 | /// Connects to a server through a WebSocket connection. Needs two callbacks; one is passed 123 | /// data, the other is passed updates about the WebSocket's status. 124 | pub fn connect( 125 | url: &str, 126 | callback: Callback, 127 | notification: Callback, 128 | ) -> Result 129 | where 130 | OUT: From + From, 131 | { 132 | let ConnectCommon(ws, listeners) = Self::connect_common(url, ¬ification)?; 133 | let listener = EventListener::new(&ws, "message", move |event: &Event| { 134 | let event = event.dyn_ref::().unwrap(); 135 | process_both(event, &callback); 136 | }); 137 | Ok(WebSocketTask::new(ws, notification, listener, listeners)) 138 | } 139 | 140 | /// Connects to a server through a WebSocket connection, like connect, 141 | /// but only processes binary frames. Text frames are silently 142 | /// ignored. Needs two functions to generate data and notification 143 | /// messages. 144 | pub fn connect_binary( 145 | url: &str, 146 | callback: Callback, 147 | notification: Callback, 148 | ) -> Result 149 | where 150 | OUT: From, 151 | { 152 | let ConnectCommon(ws, listeners) = Self::connect_common(url, ¬ification)?; 153 | let listener = EventListener::new(&ws, "message", move |event: &Event| { 154 | let event = event.dyn_ref::().unwrap(); 155 | process_binary(event, &callback); 156 | }); 157 | Ok(WebSocketTask::new(ws, notification, listener, listeners)) 158 | } 159 | 160 | /// Connects to a server through a WebSocket connection, like connect, 161 | /// but only processes text frames. Binary frames are silently 162 | /// ignored. Needs two functions to generate data and notification 163 | /// messages. 164 | pub fn connect_text( 165 | url: &str, 166 | callback: Callback, 167 | notification: Callback, 168 | ) -> Result 169 | where 170 | OUT: From, 171 | { 172 | let ConnectCommon(ws, listeners) = Self::connect_common(url, ¬ification)?; 173 | let listener = EventListener::new(&ws, "message", move |event: &Event| { 174 | let event = event.dyn_ref::().unwrap(); 175 | process_text(event, &callback); 176 | }); 177 | Ok(WebSocketTask::new(ws, notification, listener, listeners)) 178 | } 179 | 180 | fn connect_common( 181 | url: &str, 182 | notification: &Callback, 183 | ) -> Result { 184 | let ws = WebSocket::new(url); 185 | 186 | let ws = ws.map_err(|ws_error| { 187 | WebSocketError::CreationError( 188 | ws_error 189 | .unchecked_into::() 190 | .to_string() 191 | .as_string() 192 | .unwrap(), 193 | ) 194 | })?; 195 | 196 | ws.set_binary_type(BinaryType::Arraybuffer); 197 | let notify = notification.clone(); 198 | let listener_open = move |_: &Event| { 199 | notify.emit(WebSocketStatus::Opened); 200 | }; 201 | let notify = notification.clone(); 202 | let listener_close = move |_: &Event| { 203 | notify.emit(WebSocketStatus::Closed); 204 | }; 205 | let notify = notification.clone(); 206 | let listener_error = move |_: &Event| { 207 | notify.emit(WebSocketStatus::Error); 208 | }; 209 | { 210 | let listeners = [ 211 | EventListener::new(&ws, "open", listener_open), 212 | EventListener::new(&ws, "close", listener_close), 213 | EventListener::new(&ws, "error", listener_error), 214 | ]; 215 | Ok(ConnectCommon(ws, listeners)) 216 | } 217 | } 218 | } 219 | 220 | struct ConnectCommon(WebSocket, [EventListener; 3]); 221 | 222 | fn process_binary(event: &MessageEvent, callback: &Callback) 223 | where 224 | OUT: From, 225 | { 226 | let bytes = if !event.data().is_string() { 227 | Some(event.data()) 228 | } else { 229 | None 230 | }; 231 | 232 | let data = if let Some(bytes) = bytes { 233 | let bytes: Vec = Uint8Array::new(&bytes).to_vec(); 234 | Ok(bytes) 235 | } else { 236 | Err(FormatError::ReceivedTextForBinary.into()) 237 | }; 238 | 239 | let out = OUT::from(data); 240 | callback.emit(out); 241 | } 242 | 243 | fn process_text(event: &MessageEvent, callback: &Callback) 244 | where 245 | OUT: From, 246 | { 247 | let text = event.data().as_string(); 248 | 249 | let data = if let Some(text) = text { 250 | Ok(text) 251 | } else { 252 | Err(FormatError::ReceivedBinaryForText.into()) 253 | }; 254 | 255 | let out = OUT::from(data); 256 | callback.emit(out); 257 | } 258 | 259 | fn process_both(event: &MessageEvent, callback: &Callback) 260 | where 261 | OUT: From + From, 262 | { 263 | let is_text = event.data().is_string(); 264 | if is_text { 265 | process_text(event, callback); 266 | } else { 267 | process_binary(event, callback); 268 | } 269 | } 270 | 271 | impl WebSocketTask { 272 | /// Sends data to a WebSocket connection. 273 | pub fn send(&mut self, data: String) { 274 | let result = self.ws.send_with_str(&data); 275 | 276 | if result.is_err() { 277 | self.notification.emit(WebSocketStatus::Error); 278 | } 279 | } 280 | 281 | /// Sends binary data to a WebSocket connection. 282 | pub fn send_binary(&self, data: Vec) { 283 | let result = self.ws.send_with_u8_array(&data); 284 | 285 | if result.is_err() { 286 | self.notification.emit(WebSocketStatus::Error); 287 | } 288 | } 289 | } 290 | 291 | impl WebSocketTask { 292 | fn is_active(&self) -> bool { 293 | matches!( 294 | self.ws.ready_state(), 295 | WebSocket::CONNECTING | WebSocket::OPEN 296 | ) 297 | } 298 | } 299 | 300 | impl Drop for WebSocketTask { 301 | fn drop(&mut self) { 302 | if self.is_active() { 303 | self.ws.close().ok(); 304 | } 305 | } 306 | } 307 | --------------------------------------------------------------------------------