├── .github ├── FUNDING.yml └── workflows │ ├── CI.yml │ └── Release.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── README.md ├── build.rs ├── models └── cooking.model.bin ├── proto └── fasttext_serving.proto ├── pyproject.toml ├── python ├── MANIFEST.in ├── README.md ├── fasttext_serving │ ├── __init__.py │ ├── predict_pb2.py │ └── predict_pb2_grpc.py ├── setup.cfg └── setup.py └── src ├── grpc.rs ├── http.rs └── main.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: messense 2 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: CI 4 | 5 | jobs: 6 | check: 7 | name: Check 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | with: 12 | submodules: recursive 13 | - name: Cache cargo build 14 | uses: actions/cache@v1 15 | with: 16 | path: target 17 | key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} 18 | - uses: arduino/setup-protoc@v1 19 | with: 20 | repo-token: ${{ secrets.GITHUB_TOKEN }} 21 | - uses: actions-rs/toolchain@v1 22 | with: 23 | profile: minimal 24 | toolchain: stable 25 | override: true 26 | - run: cargo check 27 | 28 | test: 29 | name: Test Suite 30 | runs-on: ${{ matrix.os }} 31 | strategy: 32 | matrix: 33 | os: [ubuntu-latest, macos-latest, windows-latest] 34 | steps: 35 | - uses: actions/checkout@v3 36 | with: 37 | submodules: recursive 38 | - name: Cache cargo build 39 | uses: actions/cache@v1 40 | with: 41 | path: target 42 | key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} 43 | - uses: arduino/setup-protoc@v1 44 | with: 45 | repo-token: ${{ secrets.GITHUB_TOKEN }} 46 | - uses: actions-rs/toolchain@v1 47 | with: 48 | profile: minimal 49 | toolchain: stable 50 | override: true 51 | - run: cargo test 52 | 53 | fmt: 54 | name: Rustfmt 55 | runs-on: ubuntu-latest 56 | steps: 57 | - uses: actions/checkout@v3 58 | - uses: actions-rs/toolchain@v1 59 | with: 60 | profile: minimal 61 | toolchain: stable 62 | components: rustfmt 63 | override: true 64 | - run: cargo fmt --all -- --check 65 | -------------------------------------------------------------------------------- /.github/workflows/Release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | github-docker: 10 | name: GitHub Release and Docker image 11 | runs-on: ubuntu-18.04 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | submodules: recursive 16 | - uses: arduino/setup-protoc@v1 17 | with: 18 | repo-token: ${{ secrets.GITHUB_TOKEN }} 19 | - uses: actions-rs/toolchain@v1 20 | with: 21 | profile: minimal 22 | toolchain: stable 23 | override: true 24 | - uses: actions-rs/cargo@v1 25 | env: 26 | CARGO_INCREMENTAL: 0 27 | with: 28 | command: build 29 | args: --release 30 | - name: Create GitHub Release 31 | uses: softprops/action-gh-release@v1 32 | with: 33 | files: | 34 | target/release/fasttext-serving 35 | env: 36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 37 | - name: Push Docker image to Docker Hub 38 | uses: docker/build-push-action@v1 39 | with: 40 | username: ${{ secrets.DOCKER_USERNAME }} 41 | password: ${{ secrets.DOCKER_PASSWORD }} 42 | repository: messense/fasttext-serving 43 | tag_with_ref: true 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | .pytest_cache/ 8 | *.py[cod] 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | .venv 16 | env/ 17 | bin/ 18 | build/ 19 | develop-eggs/ 20 | dist/ 21 | eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | include/ 28 | man/ 29 | venv/ 30 | *.egg-info/ 31 | .installed.cfg 32 | *.egg 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | pip-selfcheck.json 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | 47 | # Translations 48 | *.mo 49 | 50 | # Mr Developer 51 | .mr.developer.cfg 52 | .project 53 | .pydevproject 54 | 55 | # Rope 56 | .ropeproject 57 | 58 | # Django stuff: 59 | *.log 60 | *.pot 61 | 62 | # Sphinx documentation 63 | docs/_build/ 64 | 65 | # PyCharm 66 | .idea/ 67 | 68 | # VSCode 69 | .vscode/ 70 | 71 | # Pyenv 72 | .python-version 73 | -------------------------------------------------------------------------------- /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 = "actix-codec" 7 | version = "0.5.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe" 10 | dependencies = [ 11 | "bitflags", 12 | "bytes", 13 | "futures-core", 14 | "futures-sink", 15 | "log", 16 | "memchr", 17 | "pin-project-lite", 18 | "tokio", 19 | "tokio-util", 20 | ] 21 | 22 | [[package]] 23 | name = "actix-http" 24 | version = "3.2.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724" 27 | dependencies = [ 28 | "actix-codec", 29 | "actix-rt", 30 | "actix-service", 31 | "actix-utils", 32 | "ahash", 33 | "base64", 34 | "bitflags", 35 | "bytes", 36 | "bytestring", 37 | "derive_more", 38 | "encoding_rs", 39 | "futures-core", 40 | "h2", 41 | "http", 42 | "httparse", 43 | "httpdate", 44 | "itoa", 45 | "language-tags", 46 | "local-channel", 47 | "mime", 48 | "percent-encoding", 49 | "pin-project-lite", 50 | "rand", 51 | "sha1", 52 | "smallvec", 53 | "tracing", 54 | ] 55 | 56 | [[package]] 57 | name = "actix-macros" 58 | version = "0.2.3" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" 61 | dependencies = [ 62 | "quote", 63 | "syn", 64 | ] 65 | 66 | [[package]] 67 | name = "actix-router" 68 | version = "0.5.1" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" 71 | dependencies = [ 72 | "bytestring", 73 | "http", 74 | "regex", 75 | "serde", 76 | "tracing", 77 | ] 78 | 79 | [[package]] 80 | name = "actix-rt" 81 | version = "2.7.0" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000" 84 | dependencies = [ 85 | "actix-macros", 86 | "futures-core", 87 | "tokio", 88 | ] 89 | 90 | [[package]] 91 | name = "actix-server" 92 | version = "2.1.1" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824" 95 | dependencies = [ 96 | "actix-rt", 97 | "actix-service", 98 | "actix-utils", 99 | "futures-core", 100 | "futures-util", 101 | "mio", 102 | "num_cpus", 103 | "socket2", 104 | "tokio", 105 | "tracing", 106 | ] 107 | 108 | [[package]] 109 | name = "actix-service" 110 | version = "2.0.2" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" 113 | dependencies = [ 114 | "futures-core", 115 | "paste", 116 | "pin-project-lite", 117 | ] 118 | 119 | [[package]] 120 | name = "actix-utils" 121 | version = "3.0.1" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" 124 | dependencies = [ 125 | "local-waker", 126 | "pin-project-lite", 127 | ] 128 | 129 | [[package]] 130 | name = "actix-web" 131 | version = "4.2.1" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9" 134 | dependencies = [ 135 | "actix-codec", 136 | "actix-http", 137 | "actix-router", 138 | "actix-rt", 139 | "actix-server", 140 | "actix-service", 141 | "actix-utils", 142 | "ahash", 143 | "bytes", 144 | "bytestring", 145 | "cfg-if", 146 | "derive_more", 147 | "encoding_rs", 148 | "futures-core", 149 | "futures-util", 150 | "http", 151 | "itoa", 152 | "language-tags", 153 | "log", 154 | "mime", 155 | "once_cell", 156 | "pin-project-lite", 157 | "regex", 158 | "serde", 159 | "serde_json", 160 | "serde_urlencoded", 161 | "smallvec", 162 | "socket2", 163 | "time", 164 | "url", 165 | ] 166 | 167 | [[package]] 168 | name = "ahash" 169 | version = "0.7.6" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 172 | dependencies = [ 173 | "getrandom", 174 | "once_cell", 175 | "version_check", 176 | ] 177 | 178 | [[package]] 179 | name = "aho-corasick" 180 | version = "0.7.20" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 183 | dependencies = [ 184 | "memchr", 185 | ] 186 | 187 | [[package]] 188 | name = "anyhow" 189 | version = "1.0.68" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" 192 | 193 | [[package]] 194 | name = "async-stream" 195 | version = "0.3.3" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" 198 | dependencies = [ 199 | "async-stream-impl", 200 | "futures-core", 201 | ] 202 | 203 | [[package]] 204 | name = "async-stream-impl" 205 | version = "0.3.3" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" 208 | dependencies = [ 209 | "proc-macro2", 210 | "quote", 211 | "syn", 212 | ] 213 | 214 | [[package]] 215 | name = "async-trait" 216 | version = "0.1.61" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" 219 | dependencies = [ 220 | "proc-macro2", 221 | "quote", 222 | "syn", 223 | ] 224 | 225 | [[package]] 226 | name = "atty" 227 | version = "0.2.14" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 230 | dependencies = [ 231 | "hermit-abi 0.1.19", 232 | "libc", 233 | "winapi", 234 | ] 235 | 236 | [[package]] 237 | name = "autocfg" 238 | version = "1.1.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 241 | 242 | [[package]] 243 | name = "axum" 244 | version = "0.6.1" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48" 247 | dependencies = [ 248 | "async-trait", 249 | "axum-core", 250 | "bitflags", 251 | "bytes", 252 | "futures-util", 253 | "http", 254 | "http-body", 255 | "hyper", 256 | "itoa", 257 | "matchit", 258 | "memchr", 259 | "mime", 260 | "percent-encoding", 261 | "pin-project-lite", 262 | "rustversion", 263 | "serde", 264 | "sync_wrapper", 265 | "tower", 266 | "tower-http", 267 | "tower-layer", 268 | "tower-service", 269 | ] 270 | 271 | [[package]] 272 | name = "axum-core" 273 | version = "0.3.0" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "79b8558f5a0581152dc94dcd289132a1d377494bdeafcd41869b3258e3e2ad92" 276 | dependencies = [ 277 | "async-trait", 278 | "bytes", 279 | "futures-util", 280 | "http", 281 | "http-body", 282 | "mime", 283 | "rustversion", 284 | "tower-layer", 285 | "tower-service", 286 | ] 287 | 288 | [[package]] 289 | name = "base64" 290 | version = "0.13.1" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 293 | 294 | [[package]] 295 | name = "bitflags" 296 | version = "1.3.2" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 299 | 300 | [[package]] 301 | name = "block-buffer" 302 | version = "0.10.3" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" 305 | dependencies = [ 306 | "generic-array", 307 | ] 308 | 309 | [[package]] 310 | name = "bytes" 311 | version = "1.3.0" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" 314 | 315 | [[package]] 316 | name = "bytestring" 317 | version = "1.2.0" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" 320 | dependencies = [ 321 | "bytes", 322 | ] 323 | 324 | [[package]] 325 | name = "cc" 326 | version = "1.0.78" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" 329 | 330 | [[package]] 331 | name = "cfasttext-sys" 332 | version = "0.7.3" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "b011a52d71b5ca9e4650d692065e7b3f71ad4ce26fe2827e1536aa5fa76db95c" 335 | dependencies = [ 336 | "cc", 337 | ] 338 | 339 | [[package]] 340 | name = "cfg-if" 341 | version = "1.0.0" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 344 | 345 | [[package]] 346 | name = "clap" 347 | version = "4.0.32" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" 350 | dependencies = [ 351 | "bitflags", 352 | "clap_lex", 353 | "is-terminal", 354 | "strsim", 355 | "termcolor", 356 | ] 357 | 358 | [[package]] 359 | name = "clap_lex" 360 | version = "0.3.0" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" 363 | dependencies = [ 364 | "os_str_bytes", 365 | ] 366 | 367 | [[package]] 368 | name = "convert_case" 369 | version = "0.4.0" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 372 | 373 | [[package]] 374 | name = "cpufeatures" 375 | version = "0.2.5" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 378 | dependencies = [ 379 | "libc", 380 | ] 381 | 382 | [[package]] 383 | name = "crypto-common" 384 | version = "0.1.6" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 387 | dependencies = [ 388 | "generic-array", 389 | "typenum", 390 | ] 391 | 392 | [[package]] 393 | name = "derive_more" 394 | version = "0.99.17" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" 397 | dependencies = [ 398 | "convert_case", 399 | "proc-macro2", 400 | "quote", 401 | "rustc_version", 402 | "syn", 403 | ] 404 | 405 | [[package]] 406 | name = "digest" 407 | version = "0.10.6" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" 410 | dependencies = [ 411 | "block-buffer", 412 | "crypto-common", 413 | ] 414 | 415 | [[package]] 416 | name = "either" 417 | version = "1.8.0" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" 420 | 421 | [[package]] 422 | name = "encoding_rs" 423 | version = "0.8.31" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" 426 | dependencies = [ 427 | "cfg-if", 428 | ] 429 | 430 | [[package]] 431 | name = "env_logger" 432 | version = "0.7.1" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" 435 | dependencies = [ 436 | "atty", 437 | "humantime", 438 | "log", 439 | "regex", 440 | "termcolor", 441 | ] 442 | 443 | [[package]] 444 | name = "equivalent" 445 | version = "1.0.1" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 448 | 449 | [[package]] 450 | name = "errno" 451 | version = "0.2.8" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 454 | dependencies = [ 455 | "errno-dragonfly", 456 | "libc", 457 | "winapi", 458 | ] 459 | 460 | [[package]] 461 | name = "errno-dragonfly" 462 | version = "0.1.2" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 465 | dependencies = [ 466 | "cc", 467 | "libc", 468 | ] 469 | 470 | [[package]] 471 | name = "fastrand" 472 | version = "1.8.0" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 475 | dependencies = [ 476 | "instant", 477 | ] 478 | 479 | [[package]] 480 | name = "fasttext" 481 | version = "0.7.3" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "9f4398e5c3624ba00990342afae9ec1335759214ba60f71775cdaac368ebd27e" 484 | dependencies = [ 485 | "cfasttext-sys", 486 | ] 487 | 488 | [[package]] 489 | name = "fasttext-serving" 490 | version = "0.7.0" 491 | dependencies = [ 492 | "actix-rt", 493 | "actix-web", 494 | "bytes", 495 | "clap", 496 | "fasttext", 497 | "futures", 498 | "jemallocator", 499 | "log", 500 | "mimalloc", 501 | "num_cpus", 502 | "pretty_env_logger", 503 | "prost", 504 | "serde", 505 | "tokio", 506 | "tonic", 507 | "tonic-build", 508 | "tonic-reflection", 509 | ] 510 | 511 | [[package]] 512 | name = "fixedbitset" 513 | version = "0.4.2" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 516 | 517 | [[package]] 518 | name = "fnv" 519 | version = "1.0.7" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 522 | 523 | [[package]] 524 | name = "form_urlencoded" 525 | version = "1.1.0" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 528 | dependencies = [ 529 | "percent-encoding", 530 | ] 531 | 532 | [[package]] 533 | name = "fs_extra" 534 | version = "1.2.0" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" 537 | 538 | [[package]] 539 | name = "futures" 540 | version = "0.3.25" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" 543 | dependencies = [ 544 | "futures-channel", 545 | "futures-core", 546 | "futures-io", 547 | "futures-sink", 548 | "futures-task", 549 | "futures-util", 550 | ] 551 | 552 | [[package]] 553 | name = "futures-channel" 554 | version = "0.3.25" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" 557 | dependencies = [ 558 | "futures-core", 559 | "futures-sink", 560 | ] 561 | 562 | [[package]] 563 | name = "futures-core" 564 | version = "0.3.25" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" 567 | 568 | [[package]] 569 | name = "futures-io" 570 | version = "0.3.25" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" 573 | 574 | [[package]] 575 | name = "futures-sink" 576 | version = "0.3.25" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" 579 | 580 | [[package]] 581 | name = "futures-task" 582 | version = "0.3.25" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" 585 | 586 | [[package]] 587 | name = "futures-util" 588 | version = "0.3.25" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" 591 | dependencies = [ 592 | "futures-core", 593 | "futures-sink", 594 | "futures-task", 595 | "pin-project-lite", 596 | "pin-utils", 597 | ] 598 | 599 | [[package]] 600 | name = "generic-array" 601 | version = "0.14.6" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 604 | dependencies = [ 605 | "typenum", 606 | "version_check", 607 | ] 608 | 609 | [[package]] 610 | name = "getrandom" 611 | version = "0.2.8" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 614 | dependencies = [ 615 | "cfg-if", 616 | "libc", 617 | "wasi", 618 | ] 619 | 620 | [[package]] 621 | name = "h2" 622 | version = "0.3.26" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 625 | dependencies = [ 626 | "bytes", 627 | "fnv", 628 | "futures-core", 629 | "futures-sink", 630 | "futures-util", 631 | "http", 632 | "indexmap 2.2.6", 633 | "slab", 634 | "tokio", 635 | "tokio-util", 636 | "tracing", 637 | ] 638 | 639 | [[package]] 640 | name = "hashbrown" 641 | version = "0.12.3" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 644 | 645 | [[package]] 646 | name = "hashbrown" 647 | version = "0.14.3" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" 650 | 651 | [[package]] 652 | name = "heck" 653 | version = "0.4.0" 654 | source = "registry+https://github.com/rust-lang/crates.io-index" 655 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 656 | 657 | [[package]] 658 | name = "hermit-abi" 659 | version = "0.1.19" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 662 | dependencies = [ 663 | "libc", 664 | ] 665 | 666 | [[package]] 667 | name = "hermit-abi" 668 | version = "0.2.6" 669 | source = "registry+https://github.com/rust-lang/crates.io-index" 670 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 671 | dependencies = [ 672 | "libc", 673 | ] 674 | 675 | [[package]] 676 | name = "http" 677 | version = "0.2.8" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 680 | dependencies = [ 681 | "bytes", 682 | "fnv", 683 | "itoa", 684 | ] 685 | 686 | [[package]] 687 | name = "http-body" 688 | version = "0.4.5" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 691 | dependencies = [ 692 | "bytes", 693 | "http", 694 | "pin-project-lite", 695 | ] 696 | 697 | [[package]] 698 | name = "http-range-header" 699 | version = "0.3.0" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" 702 | 703 | [[package]] 704 | name = "httparse" 705 | version = "1.8.0" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 708 | 709 | [[package]] 710 | name = "httpdate" 711 | version = "1.0.2" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 714 | 715 | [[package]] 716 | name = "humantime" 717 | version = "1.3.0" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" 720 | dependencies = [ 721 | "quick-error", 722 | ] 723 | 724 | [[package]] 725 | name = "hyper" 726 | version = "0.14.23" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" 729 | dependencies = [ 730 | "bytes", 731 | "futures-channel", 732 | "futures-core", 733 | "futures-util", 734 | "h2", 735 | "http", 736 | "http-body", 737 | "httparse", 738 | "httpdate", 739 | "itoa", 740 | "pin-project-lite", 741 | "socket2", 742 | "tokio", 743 | "tower-service", 744 | "tracing", 745 | "want", 746 | ] 747 | 748 | [[package]] 749 | name = "hyper-timeout" 750 | version = "0.4.1" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" 753 | dependencies = [ 754 | "hyper", 755 | "pin-project-lite", 756 | "tokio", 757 | "tokio-io-timeout", 758 | ] 759 | 760 | [[package]] 761 | name = "idna" 762 | version = "0.3.0" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 765 | dependencies = [ 766 | "unicode-bidi", 767 | "unicode-normalization", 768 | ] 769 | 770 | [[package]] 771 | name = "indexmap" 772 | version = "1.9.2" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 775 | dependencies = [ 776 | "autocfg", 777 | "hashbrown 0.12.3", 778 | ] 779 | 780 | [[package]] 781 | name = "indexmap" 782 | version = "2.2.6" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 785 | dependencies = [ 786 | "equivalent", 787 | "hashbrown 0.14.3", 788 | ] 789 | 790 | [[package]] 791 | name = "instant" 792 | version = "0.1.12" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 795 | dependencies = [ 796 | "cfg-if", 797 | ] 798 | 799 | [[package]] 800 | name = "io-lifetimes" 801 | version = "1.0.3" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" 804 | dependencies = [ 805 | "libc", 806 | "windows-sys", 807 | ] 808 | 809 | [[package]] 810 | name = "is-terminal" 811 | version = "0.4.2" 812 | source = "registry+https://github.com/rust-lang/crates.io-index" 813 | checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" 814 | dependencies = [ 815 | "hermit-abi 0.2.6", 816 | "io-lifetimes", 817 | "rustix", 818 | "windows-sys", 819 | ] 820 | 821 | [[package]] 822 | name = "itertools" 823 | version = "0.10.5" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 826 | dependencies = [ 827 | "either", 828 | ] 829 | 830 | [[package]] 831 | name = "itoa" 832 | version = "1.0.5" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 835 | 836 | [[package]] 837 | name = "jemalloc-sys" 838 | version = "0.5.2+5.3.0-patched" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "134163979b6eed9564c98637b710b40979939ba351f59952708234ea11b5f3f8" 841 | dependencies = [ 842 | "cc", 843 | "fs_extra", 844 | "libc", 845 | ] 846 | 847 | [[package]] 848 | name = "jemallocator" 849 | version = "0.5.0" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | checksum = "16c2514137880c52b0b4822b563fadd38257c1f380858addb74a400889696ea6" 852 | dependencies = [ 853 | "jemalloc-sys", 854 | "libc", 855 | ] 856 | 857 | [[package]] 858 | name = "language-tags" 859 | version = "0.3.2" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 862 | 863 | [[package]] 864 | name = "lazy_static" 865 | version = "1.4.0" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 868 | 869 | [[package]] 870 | name = "libc" 871 | version = "0.2.139" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 874 | 875 | [[package]] 876 | name = "libmimalloc-sys" 877 | version = "0.1.39" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" 880 | dependencies = [ 881 | "cc", 882 | "libc", 883 | ] 884 | 885 | [[package]] 886 | name = "linux-raw-sys" 887 | version = "0.1.4" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 890 | 891 | [[package]] 892 | name = "local-channel" 893 | version = "0.1.3" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" 896 | dependencies = [ 897 | "futures-core", 898 | "futures-sink", 899 | "futures-util", 900 | "local-waker", 901 | ] 902 | 903 | [[package]] 904 | name = "local-waker" 905 | version = "0.1.3" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" 908 | 909 | [[package]] 910 | name = "lock_api" 911 | version = "0.4.9" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 914 | dependencies = [ 915 | "autocfg", 916 | "scopeguard", 917 | ] 918 | 919 | [[package]] 920 | name = "log" 921 | version = "0.4.17" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 924 | dependencies = [ 925 | "cfg-if", 926 | ] 927 | 928 | [[package]] 929 | name = "matchit" 930 | version = "0.7.0" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" 933 | 934 | [[package]] 935 | name = "memchr" 936 | version = "2.5.0" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 939 | 940 | [[package]] 941 | name = "mimalloc" 942 | version = "0.1.39" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" 945 | dependencies = [ 946 | "libmimalloc-sys", 947 | ] 948 | 949 | [[package]] 950 | name = "mime" 951 | version = "0.3.16" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 954 | 955 | [[package]] 956 | name = "mio" 957 | version = "0.8.5" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" 960 | dependencies = [ 961 | "libc", 962 | "log", 963 | "wasi", 964 | "windows-sys", 965 | ] 966 | 967 | [[package]] 968 | name = "multimap" 969 | version = "0.8.3" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" 972 | 973 | [[package]] 974 | name = "num_cpus" 975 | version = "1.15.0" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" 978 | dependencies = [ 979 | "hermit-abi 0.2.6", 980 | "libc", 981 | ] 982 | 983 | [[package]] 984 | name = "once_cell" 985 | version = "1.17.0" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" 988 | 989 | [[package]] 990 | name = "os_str_bytes" 991 | version = "6.4.1" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" 994 | 995 | [[package]] 996 | name = "parking_lot" 997 | version = "0.12.1" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1000 | dependencies = [ 1001 | "lock_api", 1002 | "parking_lot_core", 1003 | ] 1004 | 1005 | [[package]] 1006 | name = "parking_lot_core" 1007 | version = "0.9.5" 1008 | source = "registry+https://github.com/rust-lang/crates.io-index" 1009 | checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" 1010 | dependencies = [ 1011 | "cfg-if", 1012 | "libc", 1013 | "redox_syscall", 1014 | "smallvec", 1015 | "windows-sys", 1016 | ] 1017 | 1018 | [[package]] 1019 | name = "paste" 1020 | version = "1.0.11" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" 1023 | 1024 | [[package]] 1025 | name = "percent-encoding" 1026 | version = "2.2.0" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 1029 | 1030 | [[package]] 1031 | name = "petgraph" 1032 | version = "0.6.2" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" 1035 | dependencies = [ 1036 | "fixedbitset", 1037 | "indexmap 1.9.2", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "pin-project" 1042 | version = "1.0.12" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" 1045 | dependencies = [ 1046 | "pin-project-internal", 1047 | ] 1048 | 1049 | [[package]] 1050 | name = "pin-project-internal" 1051 | version = "1.0.12" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" 1054 | dependencies = [ 1055 | "proc-macro2", 1056 | "quote", 1057 | "syn", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "pin-project-lite" 1062 | version = "0.2.9" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1065 | 1066 | [[package]] 1067 | name = "pin-utils" 1068 | version = "0.1.0" 1069 | source = "registry+https://github.com/rust-lang/crates.io-index" 1070 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1071 | 1072 | [[package]] 1073 | name = "ppv-lite86" 1074 | version = "0.2.17" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1077 | 1078 | [[package]] 1079 | name = "pretty_env_logger" 1080 | version = "0.4.0" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" 1083 | dependencies = [ 1084 | "env_logger", 1085 | "log", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "prettyplease" 1090 | version = "0.1.23" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78" 1093 | dependencies = [ 1094 | "proc-macro2", 1095 | "syn", 1096 | ] 1097 | 1098 | [[package]] 1099 | name = "proc-macro2" 1100 | version = "1.0.49" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" 1103 | dependencies = [ 1104 | "unicode-ident", 1105 | ] 1106 | 1107 | [[package]] 1108 | name = "prost" 1109 | version = "0.11.5" 1110 | source = "registry+https://github.com/rust-lang/crates.io-index" 1111 | checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592" 1112 | dependencies = [ 1113 | "bytes", 1114 | "prost-derive", 1115 | ] 1116 | 1117 | [[package]] 1118 | name = "prost-build" 1119 | version = "0.11.5" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6" 1122 | dependencies = [ 1123 | "bytes", 1124 | "heck", 1125 | "itertools", 1126 | "lazy_static", 1127 | "log", 1128 | "multimap", 1129 | "petgraph", 1130 | "prettyplease", 1131 | "prost", 1132 | "prost-types", 1133 | "regex", 1134 | "syn", 1135 | "tempfile", 1136 | "which", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "prost-derive" 1141 | version = "0.11.5" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720" 1144 | dependencies = [ 1145 | "anyhow", 1146 | "itertools", 1147 | "proc-macro2", 1148 | "quote", 1149 | "syn", 1150 | ] 1151 | 1152 | [[package]] 1153 | name = "prost-types" 1154 | version = "0.11.5" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091" 1157 | dependencies = [ 1158 | "bytes", 1159 | "prost", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "quick-error" 1164 | version = "1.2.3" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 1167 | 1168 | [[package]] 1169 | name = "quote" 1170 | version = "1.0.23" 1171 | source = "registry+https://github.com/rust-lang/crates.io-index" 1172 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 1173 | dependencies = [ 1174 | "proc-macro2", 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "rand" 1179 | version = "0.8.5" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1182 | dependencies = [ 1183 | "libc", 1184 | "rand_chacha", 1185 | "rand_core", 1186 | ] 1187 | 1188 | [[package]] 1189 | name = "rand_chacha" 1190 | version = "0.3.1" 1191 | source = "registry+https://github.com/rust-lang/crates.io-index" 1192 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1193 | dependencies = [ 1194 | "ppv-lite86", 1195 | "rand_core", 1196 | ] 1197 | 1198 | [[package]] 1199 | name = "rand_core" 1200 | version = "0.6.4" 1201 | source = "registry+https://github.com/rust-lang/crates.io-index" 1202 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1203 | dependencies = [ 1204 | "getrandom", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "redox_syscall" 1209 | version = "0.2.16" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1212 | dependencies = [ 1213 | "bitflags", 1214 | ] 1215 | 1216 | [[package]] 1217 | name = "regex" 1218 | version = "1.7.0" 1219 | source = "registry+https://github.com/rust-lang/crates.io-index" 1220 | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" 1221 | dependencies = [ 1222 | "aho-corasick", 1223 | "memchr", 1224 | "regex-syntax", 1225 | ] 1226 | 1227 | [[package]] 1228 | name = "regex-syntax" 1229 | version = "0.6.28" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 1232 | 1233 | [[package]] 1234 | name = "remove_dir_all" 1235 | version = "0.5.3" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 1238 | dependencies = [ 1239 | "winapi", 1240 | ] 1241 | 1242 | [[package]] 1243 | name = "rustc_version" 1244 | version = "0.4.0" 1245 | source = "registry+https://github.com/rust-lang/crates.io-index" 1246 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 1247 | dependencies = [ 1248 | "semver", 1249 | ] 1250 | 1251 | [[package]] 1252 | name = "rustix" 1253 | version = "0.36.6" 1254 | source = "registry+https://github.com/rust-lang/crates.io-index" 1255 | checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549" 1256 | dependencies = [ 1257 | "bitflags", 1258 | "errno", 1259 | "io-lifetimes", 1260 | "libc", 1261 | "linux-raw-sys", 1262 | "windows-sys", 1263 | ] 1264 | 1265 | [[package]] 1266 | name = "rustversion" 1267 | version = "1.0.11" 1268 | source = "registry+https://github.com/rust-lang/crates.io-index" 1269 | checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" 1270 | 1271 | [[package]] 1272 | name = "ryu" 1273 | version = "1.0.12" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 1276 | 1277 | [[package]] 1278 | name = "scopeguard" 1279 | version = "1.1.0" 1280 | source = "registry+https://github.com/rust-lang/crates.io-index" 1281 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1282 | 1283 | [[package]] 1284 | name = "semver" 1285 | version = "1.0.16" 1286 | source = "registry+https://github.com/rust-lang/crates.io-index" 1287 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" 1288 | 1289 | [[package]] 1290 | name = "serde" 1291 | version = "1.0.152" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 1294 | dependencies = [ 1295 | "serde_derive", 1296 | ] 1297 | 1298 | [[package]] 1299 | name = "serde_derive" 1300 | version = "1.0.152" 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" 1302 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 1303 | dependencies = [ 1304 | "proc-macro2", 1305 | "quote", 1306 | "syn", 1307 | ] 1308 | 1309 | [[package]] 1310 | name = "serde_json" 1311 | version = "1.0.91" 1312 | source = "registry+https://github.com/rust-lang/crates.io-index" 1313 | checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" 1314 | dependencies = [ 1315 | "itoa", 1316 | "ryu", 1317 | "serde", 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "serde_urlencoded" 1322 | version = "0.7.1" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1325 | dependencies = [ 1326 | "form_urlencoded", 1327 | "itoa", 1328 | "ryu", 1329 | "serde", 1330 | ] 1331 | 1332 | [[package]] 1333 | name = "sha1" 1334 | version = "0.10.5" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1337 | dependencies = [ 1338 | "cfg-if", 1339 | "cpufeatures", 1340 | "digest", 1341 | ] 1342 | 1343 | [[package]] 1344 | name = "signal-hook-registry" 1345 | version = "1.4.0" 1346 | source = "registry+https://github.com/rust-lang/crates.io-index" 1347 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1348 | dependencies = [ 1349 | "libc", 1350 | ] 1351 | 1352 | [[package]] 1353 | name = "slab" 1354 | version = "0.4.7" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" 1357 | dependencies = [ 1358 | "autocfg", 1359 | ] 1360 | 1361 | [[package]] 1362 | name = "smallvec" 1363 | version = "1.10.0" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1366 | 1367 | [[package]] 1368 | name = "socket2" 1369 | version = "0.4.7" 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" 1371 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" 1372 | dependencies = [ 1373 | "libc", 1374 | "winapi", 1375 | ] 1376 | 1377 | [[package]] 1378 | name = "strsim" 1379 | version = "0.10.0" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1382 | 1383 | [[package]] 1384 | name = "syn" 1385 | version = "1.0.107" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 1388 | dependencies = [ 1389 | "proc-macro2", 1390 | "quote", 1391 | "unicode-ident", 1392 | ] 1393 | 1394 | [[package]] 1395 | name = "sync_wrapper" 1396 | version = "0.1.1" 1397 | source = "registry+https://github.com/rust-lang/crates.io-index" 1398 | checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" 1399 | 1400 | [[package]] 1401 | name = "tempfile" 1402 | version = "3.3.0" 1403 | source = "registry+https://github.com/rust-lang/crates.io-index" 1404 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 1405 | dependencies = [ 1406 | "cfg-if", 1407 | "fastrand", 1408 | "libc", 1409 | "redox_syscall", 1410 | "remove_dir_all", 1411 | "winapi", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "termcolor" 1416 | version = "1.1.3" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 1419 | dependencies = [ 1420 | "winapi-util", 1421 | ] 1422 | 1423 | [[package]] 1424 | name = "time" 1425 | version = "0.3.17" 1426 | source = "registry+https://github.com/rust-lang/crates.io-index" 1427 | checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" 1428 | dependencies = [ 1429 | "itoa", 1430 | "serde", 1431 | "time-core", 1432 | "time-macros", 1433 | ] 1434 | 1435 | [[package]] 1436 | name = "time-core" 1437 | version = "0.1.0" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 1440 | 1441 | [[package]] 1442 | name = "time-macros" 1443 | version = "0.2.6" 1444 | source = "registry+https://github.com/rust-lang/crates.io-index" 1445 | checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" 1446 | dependencies = [ 1447 | "time-core", 1448 | ] 1449 | 1450 | [[package]] 1451 | name = "tinyvec" 1452 | version = "1.6.0" 1453 | source = "registry+https://github.com/rust-lang/crates.io-index" 1454 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1455 | dependencies = [ 1456 | "tinyvec_macros", 1457 | ] 1458 | 1459 | [[package]] 1460 | name = "tinyvec_macros" 1461 | version = "0.1.0" 1462 | source = "registry+https://github.com/rust-lang/crates.io-index" 1463 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1464 | 1465 | [[package]] 1466 | name = "tokio" 1467 | version = "1.24.2" 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" 1469 | checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" 1470 | dependencies = [ 1471 | "autocfg", 1472 | "bytes", 1473 | "libc", 1474 | "memchr", 1475 | "mio", 1476 | "num_cpus", 1477 | "parking_lot", 1478 | "pin-project-lite", 1479 | "signal-hook-registry", 1480 | "socket2", 1481 | "tokio-macros", 1482 | "windows-sys", 1483 | ] 1484 | 1485 | [[package]] 1486 | name = "tokio-io-timeout" 1487 | version = "1.2.0" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" 1490 | dependencies = [ 1491 | "pin-project-lite", 1492 | "tokio", 1493 | ] 1494 | 1495 | [[package]] 1496 | name = "tokio-macros" 1497 | version = "1.8.2" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" 1500 | dependencies = [ 1501 | "proc-macro2", 1502 | "quote", 1503 | "syn", 1504 | ] 1505 | 1506 | [[package]] 1507 | name = "tokio-stream" 1508 | version = "0.1.11" 1509 | source = "registry+https://github.com/rust-lang/crates.io-index" 1510 | checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" 1511 | dependencies = [ 1512 | "futures-core", 1513 | "pin-project-lite", 1514 | "tokio", 1515 | ] 1516 | 1517 | [[package]] 1518 | name = "tokio-util" 1519 | version = "0.7.4" 1520 | source = "registry+https://github.com/rust-lang/crates.io-index" 1521 | checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" 1522 | dependencies = [ 1523 | "bytes", 1524 | "futures-core", 1525 | "futures-sink", 1526 | "pin-project-lite", 1527 | "tokio", 1528 | "tracing", 1529 | ] 1530 | 1531 | [[package]] 1532 | name = "tonic" 1533 | version = "0.8.3" 1534 | source = "registry+https://github.com/rust-lang/crates.io-index" 1535 | checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" 1536 | dependencies = [ 1537 | "async-stream", 1538 | "async-trait", 1539 | "axum", 1540 | "base64", 1541 | "bytes", 1542 | "futures-core", 1543 | "futures-util", 1544 | "h2", 1545 | "http", 1546 | "http-body", 1547 | "hyper", 1548 | "hyper-timeout", 1549 | "percent-encoding", 1550 | "pin-project", 1551 | "prost", 1552 | "prost-derive", 1553 | "tokio", 1554 | "tokio-stream", 1555 | "tokio-util", 1556 | "tower", 1557 | "tower-layer", 1558 | "tower-service", 1559 | "tracing", 1560 | "tracing-futures", 1561 | ] 1562 | 1563 | [[package]] 1564 | name = "tonic-build" 1565 | version = "0.8.4" 1566 | source = "registry+https://github.com/rust-lang/crates.io-index" 1567 | checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" 1568 | dependencies = [ 1569 | "prettyplease", 1570 | "proc-macro2", 1571 | "prost-build", 1572 | "quote", 1573 | "syn", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "tonic-reflection" 1578 | version = "0.6.0" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "67494bad4dda4c9bffae901dfe14e2b2c0f760adb4706dc10beeb81799f7f7b2" 1581 | dependencies = [ 1582 | "bytes", 1583 | "prost", 1584 | "prost-types", 1585 | "tokio", 1586 | "tokio-stream", 1587 | "tonic", 1588 | ] 1589 | 1590 | [[package]] 1591 | name = "tower" 1592 | version = "0.4.13" 1593 | source = "registry+https://github.com/rust-lang/crates.io-index" 1594 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 1595 | dependencies = [ 1596 | "futures-core", 1597 | "futures-util", 1598 | "indexmap 1.9.2", 1599 | "pin-project", 1600 | "pin-project-lite", 1601 | "rand", 1602 | "slab", 1603 | "tokio", 1604 | "tokio-util", 1605 | "tower-layer", 1606 | "tower-service", 1607 | "tracing", 1608 | ] 1609 | 1610 | [[package]] 1611 | name = "tower-http" 1612 | version = "0.3.5" 1613 | source = "registry+https://github.com/rust-lang/crates.io-index" 1614 | checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" 1615 | dependencies = [ 1616 | "bitflags", 1617 | "bytes", 1618 | "futures-core", 1619 | "futures-util", 1620 | "http", 1621 | "http-body", 1622 | "http-range-header", 1623 | "pin-project-lite", 1624 | "tower", 1625 | "tower-layer", 1626 | "tower-service", 1627 | ] 1628 | 1629 | [[package]] 1630 | name = "tower-layer" 1631 | version = "0.3.2" 1632 | source = "registry+https://github.com/rust-lang/crates.io-index" 1633 | checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" 1634 | 1635 | [[package]] 1636 | name = "tower-service" 1637 | version = "0.3.2" 1638 | source = "registry+https://github.com/rust-lang/crates.io-index" 1639 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1640 | 1641 | [[package]] 1642 | name = "tracing" 1643 | version = "0.1.37" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1646 | dependencies = [ 1647 | "cfg-if", 1648 | "log", 1649 | "pin-project-lite", 1650 | "tracing-attributes", 1651 | "tracing-core", 1652 | ] 1653 | 1654 | [[package]] 1655 | name = "tracing-attributes" 1656 | version = "0.1.23" 1657 | source = "registry+https://github.com/rust-lang/crates.io-index" 1658 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 1659 | dependencies = [ 1660 | "proc-macro2", 1661 | "quote", 1662 | "syn", 1663 | ] 1664 | 1665 | [[package]] 1666 | name = "tracing-core" 1667 | version = "0.1.30" 1668 | source = "registry+https://github.com/rust-lang/crates.io-index" 1669 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 1670 | dependencies = [ 1671 | "once_cell", 1672 | ] 1673 | 1674 | [[package]] 1675 | name = "tracing-futures" 1676 | version = "0.2.5" 1677 | source = "registry+https://github.com/rust-lang/crates.io-index" 1678 | checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" 1679 | dependencies = [ 1680 | "pin-project", 1681 | "tracing", 1682 | ] 1683 | 1684 | [[package]] 1685 | name = "try-lock" 1686 | version = "0.2.4" 1687 | source = "registry+https://github.com/rust-lang/crates.io-index" 1688 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 1689 | 1690 | [[package]] 1691 | name = "typenum" 1692 | version = "1.16.0" 1693 | source = "registry+https://github.com/rust-lang/crates.io-index" 1694 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1695 | 1696 | [[package]] 1697 | name = "unicode-bidi" 1698 | version = "0.3.8" 1699 | source = "registry+https://github.com/rust-lang/crates.io-index" 1700 | checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" 1701 | 1702 | [[package]] 1703 | name = "unicode-ident" 1704 | version = "1.0.6" 1705 | source = "registry+https://github.com/rust-lang/crates.io-index" 1706 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 1707 | 1708 | [[package]] 1709 | name = "unicode-normalization" 1710 | version = "0.1.22" 1711 | source = "registry+https://github.com/rust-lang/crates.io-index" 1712 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1713 | dependencies = [ 1714 | "tinyvec", 1715 | ] 1716 | 1717 | [[package]] 1718 | name = "url" 1719 | version = "2.3.1" 1720 | source = "registry+https://github.com/rust-lang/crates.io-index" 1721 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 1722 | dependencies = [ 1723 | "form_urlencoded", 1724 | "idna", 1725 | "percent-encoding", 1726 | ] 1727 | 1728 | [[package]] 1729 | name = "version_check" 1730 | version = "0.9.4" 1731 | source = "registry+https://github.com/rust-lang/crates.io-index" 1732 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1733 | 1734 | [[package]] 1735 | name = "want" 1736 | version = "0.3.0" 1737 | source = "registry+https://github.com/rust-lang/crates.io-index" 1738 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 1739 | dependencies = [ 1740 | "log", 1741 | "try-lock", 1742 | ] 1743 | 1744 | [[package]] 1745 | name = "wasi" 1746 | version = "0.11.0+wasi-snapshot-preview1" 1747 | source = "registry+https://github.com/rust-lang/crates.io-index" 1748 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1749 | 1750 | [[package]] 1751 | name = "which" 1752 | version = "4.3.0" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" 1755 | dependencies = [ 1756 | "either", 1757 | "libc", 1758 | "once_cell", 1759 | ] 1760 | 1761 | [[package]] 1762 | name = "winapi" 1763 | version = "0.3.9" 1764 | source = "registry+https://github.com/rust-lang/crates.io-index" 1765 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1766 | dependencies = [ 1767 | "winapi-i686-pc-windows-gnu", 1768 | "winapi-x86_64-pc-windows-gnu", 1769 | ] 1770 | 1771 | [[package]] 1772 | name = "winapi-i686-pc-windows-gnu" 1773 | version = "0.4.0" 1774 | source = "registry+https://github.com/rust-lang/crates.io-index" 1775 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1776 | 1777 | [[package]] 1778 | name = "winapi-util" 1779 | version = "0.1.5" 1780 | source = "registry+https://github.com/rust-lang/crates.io-index" 1781 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1782 | dependencies = [ 1783 | "winapi", 1784 | ] 1785 | 1786 | [[package]] 1787 | name = "winapi-x86_64-pc-windows-gnu" 1788 | version = "0.4.0" 1789 | source = "registry+https://github.com/rust-lang/crates.io-index" 1790 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1791 | 1792 | [[package]] 1793 | name = "windows-sys" 1794 | version = "0.42.0" 1795 | source = "registry+https://github.com/rust-lang/crates.io-index" 1796 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1797 | dependencies = [ 1798 | "windows_aarch64_gnullvm", 1799 | "windows_aarch64_msvc", 1800 | "windows_i686_gnu", 1801 | "windows_i686_msvc", 1802 | "windows_x86_64_gnu", 1803 | "windows_x86_64_gnullvm", 1804 | "windows_x86_64_msvc", 1805 | ] 1806 | 1807 | [[package]] 1808 | name = "windows_aarch64_gnullvm" 1809 | version = "0.42.0" 1810 | source = "registry+https://github.com/rust-lang/crates.io-index" 1811 | checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" 1812 | 1813 | [[package]] 1814 | name = "windows_aarch64_msvc" 1815 | version = "0.42.0" 1816 | source = "registry+https://github.com/rust-lang/crates.io-index" 1817 | checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" 1818 | 1819 | [[package]] 1820 | name = "windows_i686_gnu" 1821 | version = "0.42.0" 1822 | source = "registry+https://github.com/rust-lang/crates.io-index" 1823 | checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" 1824 | 1825 | [[package]] 1826 | name = "windows_i686_msvc" 1827 | version = "0.42.0" 1828 | source = "registry+https://github.com/rust-lang/crates.io-index" 1829 | checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" 1830 | 1831 | [[package]] 1832 | name = "windows_x86_64_gnu" 1833 | version = "0.42.0" 1834 | source = "registry+https://github.com/rust-lang/crates.io-index" 1835 | checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" 1836 | 1837 | [[package]] 1838 | name = "windows_x86_64_gnullvm" 1839 | version = "0.42.0" 1840 | source = "registry+https://github.com/rust-lang/crates.io-index" 1841 | checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" 1842 | 1843 | [[package]] 1844 | name = "windows_x86_64_msvc" 1845 | version = "0.42.0" 1846 | source = "registry+https://github.com/rust-lang/crates.io-index" 1847 | checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" 1848 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fasttext-serving" 3 | version = "0.7.0" 4 | authors = ["Messense Lv "] 5 | description = "fastText model serving API server" 6 | edition = "2018" 7 | license = "MIT" 8 | readme = "README.md" 9 | repository = "https://github.com/messense/fasttext-serving.git" 10 | exclude = ["models/*"] 11 | 12 | [dependencies] 13 | fasttext = "0.7" 14 | clap = { version = "4.0", features = ["string"] } 15 | log = "0.4.4" 16 | pretty_env_logger = "0.4.0" 17 | num_cpus = "1.8.0" 18 | actix-web = { version = "4.0.0-beta.10", default-features = false, optional = true } 19 | serde = { version = "1.0.92", features = ["derive"] } 20 | # grpc dependencies 21 | prost = { version = "0.11", optional = true } 22 | tonic = { version = "0.8.0", optional = true } 23 | tonic-reflection = { version = "0.6.0", optional = true } 24 | futures = { version = "0.3", default-features = false, features = ["alloc"], optional = true } 25 | tokio = { version = "1.24", features = ["rt-multi-thread", "time", "macros"], optional = true } 26 | bytes = { version = "1.0", optional = true } 27 | 28 | [target.'cfg(all(unix, not(target_env = "musl"), not(target_arch = "aarch64")))'.dependencies] 29 | jemallocator = { version = "0.5.0", features= ["unprefixed_malloc_on_supported_platforms"] } 30 | 31 | [target.'cfg(windows)'.dependencies] 32 | mimalloc = {version = "0.1"} 33 | 34 | [build-dependencies] 35 | tonic-build = { version = "0.8.0", default-features = false, features = ["transport", "prost"], optional = true } 36 | 37 | [features] 38 | default = ["http", "grpc"] 39 | http = ["actix-web"] 40 | grpc = ["tonic", "tokio", "futures", "prost", "bytes", "tonic-build", "tonic-reflection"] 41 | 42 | [profile.release] 43 | lto = true 44 | 45 | [dev-dependencies] 46 | actix-rt = "2.3.0" 47 | 48 | [package.metadata.maturin] 49 | name = "fasttext-serving-server" 50 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | COPY target/release/fasttext-serving /usr/bin/fasttext-serving 4 | 5 | ENTRYPOINT ["/usr/bin/fasttext-serving"] 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 messense 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | 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 | 23 | fastText license: 24 | 25 | BSD License 26 | 27 | For fastText software 28 | 29 | Copyright (c) 2016-present, Facebook, Inc. All rights reserved. 30 | 31 | Redistribution and use in source and binary forms, with or without modification, 32 | are permitted provided that the following conditions are met: 33 | 34 | * Redistributions of source code must retain the above copyright notice, this 35 | list of conditions and the following disclaimer. 36 | 37 | * Redistributions in binary form must reproduce the above copyright notice, 38 | this list of conditions and the following disclaimer in the documentation 39 | and/or other materials provided with the distribution. 40 | 41 | * Neither the name Facebook nor the names of its contributors may be used to 42 | endorse or promote products derived from this software without specific 43 | prior written permission. 44 | 45 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 46 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 47 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 48 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 49 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 51 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 52 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 54 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fasttext-serving 2 | 3 | [![GitHub Actions](https://github.com/messense/fasttext-serving/workflows/CI/badge.svg)](https://github.com/messense/fasttext-serving/actions?query=workflow%3ACI) 4 | [![Crates.io](https://img.shields.io/crates/v/fasttext-serving.svg)](https://crates.io/crates/fasttext-serving) 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/messense/fasttext-serving)](https://hub.docker.com/r/messense/fasttext-serving) 6 | 7 | fastText model serving service 8 | 9 | ## Installation 10 | 11 | You can download prebuilt binary from [GitHub releases](https://github.com/messense/fasttext-serving/releases), 12 | or install it using Cargo: 13 | 14 | ```bash 15 | cargo install fasttext-serving 16 | ``` 17 | 18 | Using Docker: 19 | 20 | ```bash 21 | docker pull messense/fasttext-serving 22 | ``` 23 | 24 | ## Usage 25 | 26 | ```bash 27 | $ fasttext-serving --help 28 | 29 | USAGE: 30 | fasttext-serving [OPTIONS] --model 31 | 32 | FLAGS: 33 | --grpc Serving gRPC API instead of HTTP API 34 | -h, --help Prints help information 35 | -V, --version Prints version information 36 | 37 | OPTIONS: 38 | -a, --address
Listen address [default: 127.0.0.1] 39 | -m, --model Model path 40 | -p, --port Listen port [default: 8000] 41 | -w, --workers Worker thread count, defaults to CPU count 42 | ``` 43 | 44 | ### Serve HTTP REST API 45 | 46 | HTTP API endpoint: 47 | 48 | ``` 49 | POST /predict 50 | ``` 51 | 52 | Post data should be JSON array of string, for example `["abc", "def"]` 53 | 54 | CURL example: 55 | 56 | ```bash 57 | $ curl -X POST -H 'Content-Type: application/json' \ 58 | --data "[\"Which baking dish is best to bake a banana bread?\", \"Why not put knives in the dishwasher?\"]" \ 59 | 'http://localhost:8000/predict' 60 | [[["baking"],[0.7152988]],[["equipment"],[0.73479545]]] 61 | ``` 62 | 63 | ### Serve gRPC API 64 | 65 | Run the command with `--grpc` to serve gRPC API instead of HTTP REST API. 66 | 67 | Please refer to gRPC Python client documentation [here](./python). 68 | 69 | ## License 70 | 71 | This work is released under the MIT license. A copy of the license is provided in the [LICENSE](./LICENSE) file. 72 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | #[cfg(feature = "grpc")] 3 | { 4 | use std::env; 5 | use std::path::PathBuf; 6 | 7 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 8 | tonic_build::configure() 9 | .file_descriptor_set_path(out_dir.join("fasttext_serving_descriptor.bin")) 10 | .compile(&["proto/fasttext_serving.proto"], &["proto"]) 11 | .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /models/cooking.model.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messense/fasttext-serving/f1a322fcc2aa8c15888081c68cbfba7f6fb757cf/models/cooking.model.bin -------------------------------------------------------------------------------- /proto/fasttext_serving.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package fasttext_serving; 4 | 5 | service FasttextServing { 6 | rpc predict(stream PredictRequest) returns (PredictResponse) {} 7 | rpc sentence_vector(stream SentenceVectorRequest) 8 | returns (SentenceVectorResponse) {} 9 | } 10 | 11 | message PredictRequest { 12 | required string text = 1; 13 | optional uint32 k = 2 [ default = 1 ]; 14 | optional float threshold = 3 [ default = 0.0 ]; 15 | } 16 | 17 | message Prediction { 18 | repeated string labels = 1; 19 | repeated float probs = 2; 20 | } 21 | 22 | message PredictResponse { repeated Prediction predictions = 1; } 23 | 24 | message SentenceVectorRequest { required string text = 1; } 25 | 26 | message SentenceVector { repeated float values = 1; } 27 | 28 | message SentenceVectorResponse { repeated SentenceVector vectors = 1; } 29 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["maturin"] 3 | build-backend = "maturin" 4 | 5 | [tool.maturin] 6 | bindings = "bin" 7 | -------------------------------------------------------------------------------- /python/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # fasttext-serving 2 | 3 | fasttext-serving gRPC client 4 | 5 | ## Installation 6 | 7 | ```bash 8 | pip install fasttext-serving 9 | ``` 10 | 11 | ## Usage 12 | 13 | 14 | ```python 15 | from fasttext_serving import FasttextServing 16 | 17 | 18 | client = FasttextServing('127.0.0.1:8000') 19 | predictions = list(client.predict(['abc def'])) 20 | ``` 21 | -------------------------------------------------------------------------------- /python/fasttext_serving/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import grpc 3 | 4 | from .predict_pb2 import PredictRequest 5 | from .predict_pb2_grpc import FasttextServingStub 6 | 7 | 8 | __all__ = ['FasttextServing'] 9 | 10 | 11 | class FasttextServing(object): 12 | def __init__(self, host, options=None, secure=False, credentials=None): 13 | options = options or [ 14 | ('grpc.max_send_message_length', 10 * 1024 * 1024), # 10MB 15 | ('grpc.max_receive_message_length', 10 * 1024 * 1024), # 10MB 16 | ] 17 | if not secure: 18 | self.channel = grpc.insecure_channel(host, options=options) 19 | else: 20 | credentials = credentials or grpc.ssl_channel_credentials() 21 | self.channel = grpc.secure_channel(host, credentials, options=options) 22 | self.stub = FasttextServingStub(self.channel) 23 | 24 | def predict(self, texts, k=1, threshold=0.0): 25 | def _generate(): 26 | for text in texts: 27 | yield PredictRequest(text=text, k=k, threshold=threshold) 28 | 29 | resp = self.stub.predict(_generate()) 30 | for prediction in resp.predictions: 31 | yield prediction.labels, prediction.probs 32 | 33 | -------------------------------------------------------------------------------- /python/fasttext_serving/predict_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: predict.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import message as _message 8 | from google.protobuf import reflection as _reflection 9 | from google.protobuf import symbol_database as _symbol_database 10 | # @@protoc_insertion_point(imports) 11 | 12 | _sym_db = _symbol_database.Default() 13 | 14 | 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='predict.proto', 19 | package='fasttext_serving', 20 | syntax='proto2', 21 | serialized_options=None, 22 | serialized_pb=_b('\n\rpredict.proto\x12\x10\x66\x61sttext_serving\"B\n\x0ePredictRequest\x12\x0c\n\x04text\x18\x01 \x02(\t\x12\x0c\n\x01k\x18\x02 \x01(\r:\x01\x31\x12\x14\n\tthreshold\x18\x03 \x01(\x02:\x01\x30\"+\n\nPrediction\x12\x0e\n\x06labels\x18\x01 \x03(\t\x12\r\n\x05probs\x18\x02 \x03(\x02\"D\n\x0fPredictResponse\x12\x31\n\x0bpredictions\x18\x01 \x03(\x0b\x32\x1c.fasttext_serving.Prediction2e\n\x0f\x46\x61sttextServing\x12R\n\x07predict\x12 .fasttext_serving.PredictRequest\x1a!.fasttext_serving.PredictResponse\"\x00(\x01') 23 | ) 24 | 25 | 26 | 27 | 28 | _PREDICTREQUEST = _descriptor.Descriptor( 29 | name='PredictRequest', 30 | full_name='fasttext_serving.PredictRequest', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | fields=[ 35 | _descriptor.FieldDescriptor( 36 | name='text', full_name='fasttext_serving.PredictRequest.text', index=0, 37 | number=1, type=9, cpp_type=9, label=2, 38 | has_default_value=False, default_value=_b("").decode('utf-8'), 39 | message_type=None, enum_type=None, containing_type=None, 40 | is_extension=False, extension_scope=None, 41 | serialized_options=None, file=DESCRIPTOR), 42 | _descriptor.FieldDescriptor( 43 | name='k', full_name='fasttext_serving.PredictRequest.k', index=1, 44 | number=2, type=13, cpp_type=3, label=1, 45 | has_default_value=True, default_value=1, 46 | message_type=None, enum_type=None, containing_type=None, 47 | is_extension=False, extension_scope=None, 48 | serialized_options=None, file=DESCRIPTOR), 49 | _descriptor.FieldDescriptor( 50 | name='threshold', full_name='fasttext_serving.PredictRequest.threshold', index=2, 51 | number=3, type=2, cpp_type=6, label=1, 52 | has_default_value=True, default_value=float(0), 53 | message_type=None, enum_type=None, containing_type=None, 54 | is_extension=False, extension_scope=None, 55 | serialized_options=None, file=DESCRIPTOR), 56 | ], 57 | extensions=[ 58 | ], 59 | nested_types=[], 60 | enum_types=[ 61 | ], 62 | serialized_options=None, 63 | is_extendable=False, 64 | syntax='proto2', 65 | extension_ranges=[], 66 | oneofs=[ 67 | ], 68 | serialized_start=35, 69 | serialized_end=101, 70 | ) 71 | 72 | 73 | _PREDICTION = _descriptor.Descriptor( 74 | name='Prediction', 75 | full_name='fasttext_serving.Prediction', 76 | filename=None, 77 | file=DESCRIPTOR, 78 | containing_type=None, 79 | fields=[ 80 | _descriptor.FieldDescriptor( 81 | name='labels', full_name='fasttext_serving.Prediction.labels', index=0, 82 | number=1, type=9, cpp_type=9, label=3, 83 | has_default_value=False, default_value=[], 84 | message_type=None, enum_type=None, containing_type=None, 85 | is_extension=False, extension_scope=None, 86 | serialized_options=None, file=DESCRIPTOR), 87 | _descriptor.FieldDescriptor( 88 | name='probs', full_name='fasttext_serving.Prediction.probs', index=1, 89 | number=2, type=2, cpp_type=6, label=3, 90 | has_default_value=False, default_value=[], 91 | message_type=None, enum_type=None, containing_type=None, 92 | is_extension=False, extension_scope=None, 93 | serialized_options=None, file=DESCRIPTOR), 94 | ], 95 | extensions=[ 96 | ], 97 | nested_types=[], 98 | enum_types=[ 99 | ], 100 | serialized_options=None, 101 | is_extendable=False, 102 | syntax='proto2', 103 | extension_ranges=[], 104 | oneofs=[ 105 | ], 106 | serialized_start=103, 107 | serialized_end=146, 108 | ) 109 | 110 | 111 | _PREDICTRESPONSE = _descriptor.Descriptor( 112 | name='PredictResponse', 113 | full_name='fasttext_serving.PredictResponse', 114 | filename=None, 115 | file=DESCRIPTOR, 116 | containing_type=None, 117 | fields=[ 118 | _descriptor.FieldDescriptor( 119 | name='predictions', full_name='fasttext_serving.PredictResponse.predictions', index=0, 120 | number=1, type=11, cpp_type=10, label=3, 121 | has_default_value=False, default_value=[], 122 | message_type=None, enum_type=None, containing_type=None, 123 | is_extension=False, extension_scope=None, 124 | serialized_options=None, file=DESCRIPTOR), 125 | ], 126 | extensions=[ 127 | ], 128 | nested_types=[], 129 | enum_types=[ 130 | ], 131 | serialized_options=None, 132 | is_extendable=False, 133 | syntax='proto2', 134 | extension_ranges=[], 135 | oneofs=[ 136 | ], 137 | serialized_start=148, 138 | serialized_end=216, 139 | ) 140 | 141 | _PREDICTRESPONSE.fields_by_name['predictions'].message_type = _PREDICTION 142 | DESCRIPTOR.message_types_by_name['PredictRequest'] = _PREDICTREQUEST 143 | DESCRIPTOR.message_types_by_name['Prediction'] = _PREDICTION 144 | DESCRIPTOR.message_types_by_name['PredictResponse'] = _PREDICTRESPONSE 145 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 146 | 147 | PredictRequest = _reflection.GeneratedProtocolMessageType('PredictRequest', (_message.Message,), dict( 148 | DESCRIPTOR = _PREDICTREQUEST, 149 | __module__ = 'predict_pb2' 150 | # @@protoc_insertion_point(class_scope:fasttext_serving.PredictRequest) 151 | )) 152 | _sym_db.RegisterMessage(PredictRequest) 153 | 154 | Prediction = _reflection.GeneratedProtocolMessageType('Prediction', (_message.Message,), dict( 155 | DESCRIPTOR = _PREDICTION, 156 | __module__ = 'predict_pb2' 157 | # @@protoc_insertion_point(class_scope:fasttext_serving.Prediction) 158 | )) 159 | _sym_db.RegisterMessage(Prediction) 160 | 161 | PredictResponse = _reflection.GeneratedProtocolMessageType('PredictResponse', (_message.Message,), dict( 162 | DESCRIPTOR = _PREDICTRESPONSE, 163 | __module__ = 'predict_pb2' 164 | # @@protoc_insertion_point(class_scope:fasttext_serving.PredictResponse) 165 | )) 166 | _sym_db.RegisterMessage(PredictResponse) 167 | 168 | 169 | 170 | _FASTTEXTSERVING = _descriptor.ServiceDescriptor( 171 | name='FasttextServing', 172 | full_name='fasttext_serving.FasttextServing', 173 | file=DESCRIPTOR, 174 | index=0, 175 | serialized_options=None, 176 | serialized_start=218, 177 | serialized_end=319, 178 | methods=[ 179 | _descriptor.MethodDescriptor( 180 | name='predict', 181 | full_name='fasttext_serving.FasttextServing.predict', 182 | index=0, 183 | containing_service=None, 184 | input_type=_PREDICTREQUEST, 185 | output_type=_PREDICTRESPONSE, 186 | serialized_options=None, 187 | ), 188 | ]) 189 | _sym_db.RegisterServiceDescriptor(_FASTTEXTSERVING) 190 | 191 | DESCRIPTOR.services_by_name['FasttextServing'] = _FASTTEXTSERVING 192 | 193 | # @@protoc_insertion_point(module_scope) 194 | -------------------------------------------------------------------------------- /python/fasttext_serving/predict_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | import grpc 3 | 4 | from . import predict_pb2 as predict__pb2 5 | 6 | 7 | class FasttextServingStub(object): 8 | # missing associated documentation comment in .proto file 9 | pass 10 | 11 | def __init__(self, channel): 12 | """Constructor. 13 | 14 | Args: 15 | channel: A grpc.Channel. 16 | """ 17 | self.predict = channel.stream_unary( 18 | '/fasttext_serving.FasttextServing/predict', 19 | request_serializer=predict__pb2.PredictRequest.SerializeToString, 20 | response_deserializer=predict__pb2.PredictResponse.FromString, 21 | ) 22 | 23 | 24 | class FasttextServingServicer(object): 25 | # missing associated documentation comment in .proto file 26 | pass 27 | 28 | def predict(self, request_iterator, context): 29 | # missing associated documentation comment in .proto file 30 | pass 31 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 32 | context.set_details('Method not implemented!') 33 | raise NotImplementedError('Method not implemented!') 34 | 35 | 36 | def add_FasttextServingServicer_to_server(servicer, server): 37 | rpc_method_handlers = { 38 | 'predict': grpc.stream_unary_rpc_method_handler( 39 | servicer.predict, 40 | request_deserializer=predict__pb2.PredictRequest.FromString, 41 | response_serializer=predict__pb2.PredictResponse.SerializeToString, 42 | ), 43 | } 44 | generic_handler = grpc.method_handlers_generic_handler( 45 | 'fasttext_serving.FasttextServing', rpc_method_handlers) 46 | server.add_generic_rpc_handlers((generic_handler,)) 47 | -------------------------------------------------------------------------------- /python/setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal=1 3 | 4 | [flake8] 5 | exclude = .svn,CVS,.bzr,.hg,.git,__pycache,.ropeproject 6 | max-line-length = 120 7 | ignore = D100,D103 8 | import-order-style = pep8 9 | application-import-names = fasttext_serving 10 | -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from setuptools import setup, find_packages 4 | 5 | readme = 'README.md' 6 | with open(readme, encoding='utf-8') as f: 7 | long_description = f.read() 8 | 9 | 10 | setup( 11 | name='fasttext-serving', 12 | version='0.2.0', 13 | author='messense', 14 | author_email='messense@icloud.com', 15 | url='https://github.com/messense/fasttext-serving', 16 | packages=find_packages(exclude=('tests', 'tests.*')), 17 | description='fasttext-serving gRPC client', 18 | long_description=long_description, 19 | long_description_content_type='text/markdown', 20 | install_requires=['grpcio', 'protobuf'], 21 | include_package_data=True, 22 | classifiers=[ 23 | 'Operating System :: MacOS', 24 | 'Operating System :: POSIX', 25 | 'Operating System :: POSIX :: Linux', 26 | 'Programming Language :: Python', 27 | 'Programming Language :: Python :: 2.7', 28 | 'Programming Language :: Python :: 3.6', 29 | 'Programming Language :: Python :: 3.7', 30 | 'Programming Language :: Python :: 3.8', 31 | 'Programming Language :: Python :: 3.9', 32 | 'Programming Language :: Python :: Implementation :: CPython', 33 | ] 34 | ) 35 | 36 | -------------------------------------------------------------------------------- /src/grpc.rs: -------------------------------------------------------------------------------- 1 | use std::net::ToSocketAddrs; 2 | use std::sync::Arc; 3 | 4 | use fasttext::FastText; 5 | use futures::StreamExt; 6 | use tonic::transport::Server; 7 | use tonic::{Request, Response, Status, Streaming}; 8 | 9 | use crate::predict_one; 10 | 11 | #[allow(non_camel_case_types)] 12 | mod proto { 13 | tonic::include_proto!("fasttext_serving"); 14 | 15 | pub(crate) const FILE_DESCRIPTOR_SET: &'static [u8] = 16 | tonic::include_file_descriptor_set!("fasttext_serving_descriptor"); 17 | } 18 | 19 | use proto::{ 20 | fasttext_serving_server as server, PredictRequest, PredictResponse, Prediction, SentenceVector, 21 | SentenceVectorRequest, SentenceVectorResponse, 22 | }; 23 | 24 | #[derive(Debug, Clone)] 25 | struct FastTextServingService { 26 | model: Arc, 27 | } 28 | 29 | #[tonic::async_trait] 30 | impl server::FasttextServing for FastTextServingService { 31 | async fn predict( 32 | &self, 33 | request: Request>, 34 | ) -> Result, Status> { 35 | let stream = request.into_inner(); 36 | futures::pin_mut!(stream); 37 | let model = self.model.clone(); 38 | let mut predictions = Vec::new(); 39 | while let Some(req) = stream.next().await { 40 | let req = req?; 41 | let text = req.text; 42 | let k = req.k.unwrap_or(1); 43 | let threshold = req.threshold.unwrap_or(0.0); 44 | let (labels, probs) = predict_one(&model, &text, k, threshold); 45 | predictions.push(Prediction { labels, probs }); 46 | } 47 | Ok(Response::new(PredictResponse { predictions })) 48 | } 49 | 50 | async fn sentence_vector( 51 | &self, 52 | request: Request>, 53 | ) -> Result, Status> { 54 | let stream = request.into_inner(); 55 | futures::pin_mut!(stream); 56 | let mut vectors = Vec::new(); 57 | let model = self.model.clone(); 58 | while let Some(req) = stream.next().await { 59 | let req = req?; 60 | let text = req.text; 61 | let values = model 62 | .get_sentence_vector(&text) 63 | .expect("get_sentence_vector failed"); 64 | vectors.push(SentenceVector { values }); 65 | } 66 | Ok(Response::new(SentenceVectorResponse { vectors })) 67 | } 68 | } 69 | 70 | pub(crate) fn runserver(model: FastText, address: &str, port: u16, num_threads: usize) { 71 | let reflection_service = tonic_reflection::server::Builder::configure() 72 | .register_encoded_file_descriptor_set(proto::FILE_DESCRIPTOR_SET) 73 | .build() 74 | .unwrap(); 75 | let instance = FastTextServingService { 76 | model: Arc::new(model), 77 | }; 78 | let service = server::FasttextServingServer::new(instance); 79 | let addr = (address, port).to_socket_addrs().unwrap().next().unwrap(); 80 | let server = Server::builder() 81 | .add_service(reflection_service) 82 | .add_service(service); 83 | log::info!("Listening on {}:{}", address, port); 84 | tokio::runtime::Builder::new_multi_thread() 85 | .enable_all() 86 | .worker_threads(num_threads) 87 | .build() 88 | .unwrap() 89 | .block_on(async { 90 | server.serve(addr).await.unwrap(); 91 | }); 92 | } 93 | 94 | // FIXME: add test case 95 | -------------------------------------------------------------------------------- /src/http.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::io; 3 | use std::str::FromStr; 4 | 5 | use actix_web::rt::System; 6 | use actix_web::{web, App, HttpServer}; 7 | use fasttext::FastText; 8 | use serde::Deserialize; 9 | 10 | use crate::predict_one; 11 | 12 | const UNIX_PREFIX: &'static str = "unix:"; 13 | 14 | enum Address { 15 | IpPort(String, u16), 16 | Unix(String), 17 | } 18 | 19 | impl From<(&str, u16)> for Address { 20 | fn from(addr: (&str, u16)) -> Self { 21 | addr.0 22 | .parse::
() 23 | .unwrap_or_else(|_| Address::IpPort(addr.0.to_string(), addr.1)) 24 | } 25 | } 26 | 27 | impl FromStr for Address { 28 | type Err = io::Error; 29 | 30 | fn from_str(string: &str) -> io::Result { 31 | #[cfg(unix)] 32 | { 33 | if string.starts_with(UNIX_PREFIX) { 34 | let address = &string[UNIX_PREFIX.len()..]; 35 | return Ok(Address::Unix(address.into())); 36 | } 37 | } 38 | Err(io::Error::new( 39 | io::ErrorKind::Other, 40 | "failed to resolve TCP address", 41 | )) 42 | } 43 | } 44 | 45 | impl fmt::Display for Address { 46 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 47 | match self { 48 | Address::IpPort(ip, port) => write!(f, "{}:{}", ip, port), 49 | Address::Unix(path) => write!(f, "{}{}", UNIX_PREFIX, path), 50 | } 51 | } 52 | } 53 | 54 | #[derive(Deserialize, Debug, Default)] 55 | struct PredictOptions { 56 | k: Option, 57 | threshold: Option, 58 | } 59 | 60 | async fn predict( 61 | model: web::Data, 62 | texts: web::Json>, 63 | options: web::Query, 64 | ) -> web::Json, Vec)>> { 65 | let k = options.k.unwrap_or(1); 66 | let threshold = options.threshold.unwrap_or(0.0); 67 | let text_count = texts.len(); 68 | let ret: Vec<(Vec, Vec)> = match text_count { 69 | 0 => Vec::new(), 70 | _ => texts 71 | .iter() 72 | .map(|txt| predict_one(model.get_ref(), txt, k, threshold)) 73 | .collect(), 74 | }; 75 | web::Json(ret) 76 | } 77 | 78 | async fn sentence_vector( 79 | model: web::Data, 80 | texts: web::Json>, 81 | ) -> web::Json>> { 82 | let text_count = texts.len(); 83 | let ret: Vec> = match text_count { 84 | 0 => Vec::new(), 85 | _ => texts 86 | .iter() 87 | .map(|txt| { 88 | model 89 | .get_sentence_vector(txt) 90 | .expect("get_sentence_vector failed") 91 | }) 92 | .collect(), 93 | }; 94 | web::Json(ret) 95 | } 96 | 97 | pub(crate) fn runserver(model: FastText, address: &str, port: u16, workers: usize) { 98 | let addr = Address::from((address, port)); 99 | log::info!("Listening on {}", addr); 100 | let model_data = web::Data::new(model); 101 | let json_cfg = web::JsonConfig::default() 102 | .limit(20_971_520) // 20MB 103 | .content_type(|_mime| true); // Accept any content type 104 | let mut server = HttpServer::new(move || { 105 | App::new() 106 | .service( 107 | web::resource("/predict") 108 | .app_data(model_data.clone()) 109 | .app_data(json_cfg.clone()) 110 | .route(web::post().to(predict)), 111 | ) 112 | .service( 113 | web::resource("/sentence-vector") 114 | .app_data(model_data.clone()) 115 | .app_data(json_cfg.clone()) 116 | .route(web::post().to(sentence_vector)), 117 | ) 118 | }) 119 | .workers(workers); 120 | 121 | let sys = System::new(); 122 | server = match addr { 123 | Address::IpPort(address, port) => server.bind((&address[..], port)).expect("bind failed"), 124 | Address::Unix(path) => { 125 | #[cfg(unix)] 126 | { 127 | server.bind_uds(path).expect("bind failed") 128 | } 129 | #[cfg(not(unix))] 130 | { 131 | panic!("Unix domain socket is not supported on this platform") 132 | } 133 | } 134 | }; 135 | sys.block_on(async { server.run().await }).unwrap(); 136 | } 137 | 138 | #[cfg(test)] 139 | mod test { 140 | use super::predict; 141 | use actix_web::http::StatusCode; 142 | use actix_web::test::{call_service, init_service, TestRequest}; 143 | use actix_web::{web, App}; 144 | use fasttext::FastText; 145 | 146 | #[actix_rt::test] 147 | async fn test_predict_empty_input() { 148 | let mut fasttext = FastText::new(); 149 | fasttext 150 | .load_model("models/cooking.model.bin") 151 | .expect("Failed to load fastText model"); 152 | let model_data = web::Data::new(fasttext); 153 | let mut srv = init_service( 154 | App::new() 155 | .app_data(model_data) 156 | .service(web::resource("/predict").route(web::post().to(predict))), 157 | ) 158 | .await; 159 | let data: Vec = Vec::new(); 160 | let req = TestRequest::post() 161 | .uri("/predict") 162 | .set_json(&data) 163 | .to_request(); 164 | let resp = call_service(&mut srv, req).await; 165 | assert_eq!(resp.status(), StatusCode::OK); 166 | } 167 | 168 | #[actix_rt::test] 169 | async fn test_predict() { 170 | let mut fasttext = FastText::new(); 171 | fasttext 172 | .load_model("models/cooking.model.bin") 173 | .expect("Failed to load fastText model"); 174 | let model_data = web::Data::new(fasttext); 175 | let mut srv = init_service( 176 | App::new() 177 | .app_data(model_data) 178 | .service(web::resource("/predict").route(web::post().to(predict))), 179 | ) 180 | .await; 181 | let data = vec!["Which baking dish is best to bake a banana bread?"]; 182 | let req = TestRequest::post() 183 | .uri("/predict") 184 | .set_json(&data) 185 | .to_request(); 186 | let resp = call_service(&mut srv, req).await; 187 | assert_eq!(resp.status(), StatusCode::OK); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::{Arg, ArgAction, Command}; 2 | use fasttext::FastText; 3 | use std::env; 4 | use std::path::Path; 5 | 6 | #[cfg(feature = "grpc")] 7 | mod grpc; 8 | #[cfg(feature = "http")] 9 | mod http; 10 | 11 | #[cfg(all(unix, not(target_env = "musl"), not(target_arch = "aarch64")))] 12 | #[global_allocator] 13 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; 14 | 15 | #[cfg(windows)] 16 | #[global_allocator] 17 | static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; 18 | 19 | #[inline] 20 | pub fn predict_one( 21 | model: &FastText, 22 | text: &str, 23 | k: u32, 24 | threshold: f32, 25 | ) -> (Vec, Vec) { 26 | // Ensure k >= 1 27 | let k = if k > 0 { k } else { 1 }; 28 | // NOTE: text needs to end in a newline 29 | // to exactly mimic the behavior of the cli 30 | let preds = if text.ends_with('\n') { 31 | model 32 | .predict(text, k as i32, threshold) 33 | .expect("predict failed") 34 | } else { 35 | let mut text = text.to_string(); 36 | text.push('\n'); 37 | model 38 | .predict(&text, k as i32, threshold) 39 | .expect("predict failed") 40 | }; 41 | let mut labels = Vec::with_capacity(preds.len()); 42 | let mut probs = Vec::with_capacity(preds.len()); 43 | for pred in &preds { 44 | labels.push(pred.label.trim_start_matches("__label__").to_string()); 45 | probs.push(pred.prob); 46 | } 47 | (labels, probs) 48 | } 49 | 50 | fn main() { 51 | if env::var("RUST_LOG").is_err() { 52 | env::set_var("RUST_LOG", "fasttext_serving=info"); 53 | } 54 | pretty_env_logger::init(); 55 | 56 | let num_threads = num_cpus::get().to_string(); 57 | let matches = Command::new("fasttext-serving") 58 | .version(env!("CARGO_PKG_VERSION")) 59 | .about("fastText model serving service") 60 | .author("Messense Lv ") 61 | .arg( 62 | Arg::new("model") 63 | .required(true) 64 | .short('m') 65 | .long("model") 66 | .value_name("model") 67 | .num_args(1) 68 | .help("Model path"), 69 | ) 70 | .arg( 71 | Arg::new("address") 72 | .short('a') 73 | .long("address") 74 | .default_value("127.0.0.1") 75 | .num_args(1) 76 | .help("Listen address"), 77 | ) 78 | .arg( 79 | Arg::new("port") 80 | .short('p') 81 | .long("port") 82 | .default_value("8000") 83 | .num_args(1) 84 | .help("Listen port"), 85 | ) 86 | .arg( 87 | Arg::new("workers") 88 | .short('w') 89 | .long("workers") 90 | .alias("concurrency") 91 | .alias("threads") 92 | .default_value(&num_threads) 93 | .num_args(1) 94 | .help("Worker thread count, defaults to CPU count"), 95 | ) 96 | .arg( 97 | Arg::new("grpc") 98 | .long("grpc") 99 | .action(ArgAction::SetTrue) 100 | .help("Serving gRPC API instead of HTTP API"), 101 | ) 102 | .get_matches(); 103 | let model_path = matches.get_one::("model").unwrap(); 104 | if !Path::new(model_path).exists() { 105 | panic!("Error: model {} does not exists", model_path); 106 | } 107 | let address = matches 108 | .get_one::("address") 109 | .expect("missing address"); 110 | let port = matches.get_one::("port").expect("missing port"); 111 | let workers = matches 112 | .get_one::("workers") 113 | .expect("missing workers"); 114 | let mut model = FastText::new(); 115 | model 116 | .load_model(model_path) 117 | .expect("Failed to load fastText model"); 118 | let port: u16 = port.parse().expect("invalid port"); 119 | let workers: usize = workers.parse().expect("invalid workers"); 120 | if matches.get_flag("grpc") { 121 | #[cfg(feature = "grpc")] 122 | crate::grpc::runserver(model, address, port, workers); 123 | #[cfg(not(feature = "grpc"))] 124 | panic!("gRPC support is not enabled!") 125 | } else { 126 | #[cfg(feature = "http")] 127 | crate::http::runserver(model, address, port, workers); 128 | #[cfg(not(feature = "http"))] 129 | panic!("HTTP support is not enabled!") 130 | } 131 | } 132 | --------------------------------------------------------------------------------