├── .github └── workflows │ ├── build-musl.yml │ └── ci.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── changes ├── v0.2.md ├── v0.3.0.md ├── v0.4.0.md ├── v0.4.1.md └── v0.4.2.md ├── check.sh ├── examples └── basic.nu └── src ├── engine.rs ├── handler.rs ├── lib.rs ├── listener.rs ├── main.rs ├── test_engine.rs ├── test_handler.rs └── to_sse.rs /.github/workflows/build-musl.yml: -------------------------------------------------------------------------------- 1 | name: Build MUSL Binary 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | name: Build MUSL Binary 11 | runs-on: ubuntu-latest 12 | container: 13 | image: rust:alpine 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Install dependencies 19 | run: apk add --no-cache musl-dev openssl-dev openssl-libs-static 20 | 21 | - name: Build binary 22 | env: 23 | OPENSSL_STATIC: true 24 | run: cargo build --release --target x86_64-unknown-linux-musl 25 | 26 | - name: Upload binary 27 | uses: actions/upload-artifact@v4 28 | with: 29 | name: binary-musl 30 | path: target/x86_64-unknown-linux-musl/release/* 31 | if-no-files-found: error 32 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Cross-platform CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | test: 14 | name: Test - ${{ matrix.os }} 15 | runs-on: ${{ matrix.os }} 16 | continue-on-error: true 17 | strategy: 18 | matrix: 19 | os: [windows-latest, macos-latest, ubuntu-latest] 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | 24 | - name: Install Rust 25 | run: | 26 | rustup update stable 27 | rustup default stable 28 | rustup component add clippy 29 | 30 | - name: Clippy 31 | run: cargo clippy -- -D warnings 32 | 33 | - name: Build 34 | run: cargo build --verbose 35 | 36 | - name: Run tests 37 | run: cargo test --verbose -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | store 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.8.11" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 25 | dependencies = [ 26 | "cfg-if", 27 | "once_cell", 28 | "version_check", 29 | "zerocopy", 30 | ] 31 | 32 | [[package]] 33 | name = "aho-corasick" 34 | version = "1.1.3" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 37 | dependencies = [ 38 | "memchr", 39 | ] 40 | 41 | [[package]] 42 | name = "alloc-no-stdlib" 43 | version = "2.0.4" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 46 | 47 | [[package]] 48 | name = "alloc-stdlib" 49 | version = "0.2.2" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 52 | dependencies = [ 53 | "alloc-no-stdlib", 54 | ] 55 | 56 | [[package]] 57 | name = "allocator-api2" 58 | version = "0.2.21" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 61 | 62 | [[package]] 63 | name = "alphanumeric-sort" 64 | version = "1.5.3" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "d67c60c5f10f11c6ee04de72b2dd98bb9d2548cbc314d22a609bfa8bd9e87e8f" 67 | 68 | [[package]] 69 | name = "android-tzdata" 70 | version = "0.1.1" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 73 | 74 | [[package]] 75 | name = "android_system_properties" 76 | version = "0.1.5" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 79 | dependencies = [ 80 | "libc", 81 | ] 82 | 83 | [[package]] 84 | name = "ansi-str" 85 | version = "0.8.0" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "1cf4578926a981ab0ca955dc023541d19de37112bc24c1a197bd806d3d86ad1d" 88 | dependencies = [ 89 | "ansitok", 90 | ] 91 | 92 | [[package]] 93 | name = "ansitok" 94 | version = "0.2.0" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "220044e6a1bb31ddee4e3db724d29767f352de47445a6cd75e1a173142136c83" 97 | dependencies = [ 98 | "nom", 99 | "vte 0.10.1", 100 | ] 101 | 102 | [[package]] 103 | name = "anstream" 104 | version = "0.6.18" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 107 | dependencies = [ 108 | "anstyle", 109 | "anstyle-parse", 110 | "anstyle-query", 111 | "anstyle-wincon", 112 | "colorchoice", 113 | "is_terminal_polyfill", 114 | "utf8parse", 115 | ] 116 | 117 | [[package]] 118 | name = "anstyle" 119 | version = "1.0.10" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 122 | 123 | [[package]] 124 | name = "anstyle-parse" 125 | version = "0.2.6" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 128 | dependencies = [ 129 | "utf8parse", 130 | ] 131 | 132 | [[package]] 133 | name = "anstyle-query" 134 | version = "1.1.2" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 137 | dependencies = [ 138 | "windows-sys 0.59.0", 139 | ] 140 | 141 | [[package]] 142 | name = "anstyle-wincon" 143 | version = "3.0.7" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 146 | dependencies = [ 147 | "anstyle", 148 | "once_cell", 149 | "windows-sys 0.59.0", 150 | ] 151 | 152 | [[package]] 153 | name = "arbitrary" 154 | version = "1.4.1" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" 157 | dependencies = [ 158 | "derive_arbitrary", 159 | ] 160 | 161 | [[package]] 162 | name = "arrayvec" 163 | version = "0.5.2" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 166 | 167 | [[package]] 168 | name = "arrayvec" 169 | version = "0.7.6" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 172 | 173 | [[package]] 174 | name = "async-stream" 175 | version = "0.3.6" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" 178 | dependencies = [ 179 | "async-stream-impl", 180 | "futures-core", 181 | "pin-project-lite", 182 | ] 183 | 184 | [[package]] 185 | name = "async-stream-impl" 186 | version = "0.3.6" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" 189 | dependencies = [ 190 | "proc-macro2", 191 | "quote", 192 | "syn", 193 | ] 194 | 195 | [[package]] 196 | name = "atomic" 197 | version = "0.6.0" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" 200 | dependencies = [ 201 | "bytemuck", 202 | ] 203 | 204 | [[package]] 205 | name = "atomic-waker" 206 | version = "1.1.2" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 209 | 210 | [[package]] 211 | name = "autocfg" 212 | version = "1.4.0" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 215 | 216 | [[package]] 217 | name = "aws-lc-rs" 218 | version = "1.12.2" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "4c2b7ddaa2c56a367ad27a094ad8ef4faacf8a617c2575acb2ba88949df999ca" 221 | dependencies = [ 222 | "aws-lc-sys", 223 | "paste", 224 | "zeroize", 225 | ] 226 | 227 | [[package]] 228 | name = "aws-lc-sys" 229 | version = "0.25.1" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "54ac4f13dad353b209b34cbec082338202cbc01c8f00336b55c750c13ac91f8f" 232 | dependencies = [ 233 | "bindgen 0.69.5", 234 | "cc", 235 | "cmake", 236 | "dunce", 237 | "fs_extra", 238 | "paste", 239 | ] 240 | 241 | [[package]] 242 | name = "backtrace" 243 | version = "0.3.74" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 246 | dependencies = [ 247 | "addr2line", 248 | "cfg-if", 249 | "libc", 250 | "miniz_oxide", 251 | "object", 252 | "rustc-demangle", 253 | "windows-targets 0.52.6", 254 | ] 255 | 256 | [[package]] 257 | name = "base64" 258 | version = "0.22.1" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 261 | 262 | [[package]] 263 | name = "bindgen" 264 | version = "0.69.5" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" 267 | dependencies = [ 268 | "bitflags 2.8.0", 269 | "cexpr", 270 | "clang-sys", 271 | "itertools 0.12.1", 272 | "lazy_static", 273 | "lazycell", 274 | "log", 275 | "prettyplease", 276 | "proc-macro2", 277 | "quote", 278 | "regex", 279 | "rustc-hash", 280 | "shlex", 281 | "syn", 282 | "which 4.4.2", 283 | ] 284 | 285 | [[package]] 286 | name = "bindgen" 287 | version = "0.70.1" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" 290 | dependencies = [ 291 | "bitflags 2.8.0", 292 | "cexpr", 293 | "clang-sys", 294 | "itertools 0.13.0", 295 | "proc-macro2", 296 | "quote", 297 | "regex", 298 | "rustc-hash", 299 | "shlex", 300 | "syn", 301 | ] 302 | 303 | [[package]] 304 | name = "bit-set" 305 | version = "0.8.0" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" 308 | dependencies = [ 309 | "bit-vec", 310 | ] 311 | 312 | [[package]] 313 | name = "bit-vec" 314 | version = "0.8.0" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" 317 | 318 | [[package]] 319 | name = "bitflags" 320 | version = "1.3.2" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 323 | 324 | [[package]] 325 | name = "bitflags" 326 | version = "2.8.0" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 329 | dependencies = [ 330 | "serde", 331 | ] 332 | 333 | [[package]] 334 | name = "block-buffer" 335 | version = "0.10.4" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 338 | dependencies = [ 339 | "generic-array", 340 | ] 341 | 342 | [[package]] 343 | name = "bracoxide" 344 | version = "0.1.5" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "7f52991c481aa9d7518254cfb6ce5726d24ff8c5d383d6422cd3793729b0962a" 347 | 348 | [[package]] 349 | name = "brotli" 350 | version = "7.0.0" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" 353 | dependencies = [ 354 | "alloc-no-stdlib", 355 | "alloc-stdlib", 356 | "brotli-decompressor", 357 | ] 358 | 359 | [[package]] 360 | name = "brotli-decompressor" 361 | version = "4.0.2" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" 364 | dependencies = [ 365 | "alloc-no-stdlib", 366 | "alloc-stdlib", 367 | ] 368 | 369 | [[package]] 370 | name = "bumpalo" 371 | version = "3.16.0" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 374 | 375 | [[package]] 376 | name = "bytecount" 377 | version = "0.6.8" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" 380 | 381 | [[package]] 382 | name = "bytemuck" 383 | version = "1.22.0" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" 386 | 387 | [[package]] 388 | name = "byteorder" 389 | version = "1.5.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 392 | 393 | [[package]] 394 | name = "bytes" 395 | version = "1.9.0" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" 398 | 399 | [[package]] 400 | name = "bytesize" 401 | version = "1.3.3" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" 404 | 405 | [[package]] 406 | name = "calamine" 407 | version = "0.26.1" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "138646b9af2c5d7f1804ea4bf93afc597737d2bd4f7341d67c48b03316976eb1" 410 | dependencies = [ 411 | "byteorder", 412 | "chrono", 413 | "codepage", 414 | "encoding_rs", 415 | "log", 416 | "quick-xml 0.31.0", 417 | "serde", 418 | "zip", 419 | ] 420 | 421 | [[package]] 422 | name = "cc" 423 | version = "1.2.10" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" 426 | dependencies = [ 427 | "jobserver", 428 | "libc", 429 | "shlex", 430 | ] 431 | 432 | [[package]] 433 | name = "cexpr" 434 | version = "0.6.0" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 437 | dependencies = [ 438 | "nom", 439 | ] 440 | 441 | [[package]] 442 | name = "cfg-if" 443 | version = "1.0.0" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 446 | 447 | [[package]] 448 | name = "cfg_aliases" 449 | version = "0.2.1" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 452 | 453 | [[package]] 454 | name = "chardetng" 455 | version = "0.1.17" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "14b8f0b65b7b08ae3c8187e8d77174de20cb6777864c6b832d8ad365999cf1ea" 458 | dependencies = [ 459 | "cfg-if", 460 | "encoding_rs", 461 | "memchr", 462 | ] 463 | 464 | [[package]] 465 | name = "chrono" 466 | version = "0.4.39" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" 469 | dependencies = [ 470 | "android-tzdata", 471 | "iana-time-zone", 472 | "js-sys", 473 | "num-traits", 474 | "pure-rust-locales", 475 | "serde", 476 | "wasm-bindgen", 477 | "windows-targets 0.52.6", 478 | ] 479 | 480 | [[package]] 481 | name = "chrono-humanize" 482 | version = "0.2.3" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "799627e6b4d27827a814e837b9d8a504832086081806d45b1afa34dc982b023b" 485 | dependencies = [ 486 | "chrono", 487 | ] 488 | 489 | [[package]] 490 | name = "chrono-tz" 491 | version = "0.10.1" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "9c6ac4f2c0bf0f44e9161aec9675e1050aa4a530663c4a9e37e108fa948bca9f" 494 | dependencies = [ 495 | "chrono", 496 | "chrono-tz-build", 497 | "phf", 498 | ] 499 | 500 | [[package]] 501 | name = "chrono-tz-build" 502 | version = "0.4.0" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "e94fea34d77a245229e7746bd2beb786cd2a896f306ff491fb8cecb3074b10a7" 505 | dependencies = [ 506 | "parse-zoneinfo", 507 | "phf_codegen", 508 | ] 509 | 510 | [[package]] 511 | name = "clang-sys" 512 | version = "1.8.1" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" 515 | dependencies = [ 516 | "glob", 517 | "libc", 518 | "libloading", 519 | ] 520 | 521 | [[package]] 522 | name = "clap" 523 | version = "4.5.27" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" 526 | dependencies = [ 527 | "clap_builder", 528 | "clap_derive", 529 | ] 530 | 531 | [[package]] 532 | name = "clap_builder" 533 | version = "4.5.27" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" 536 | dependencies = [ 537 | "anstream", 538 | "anstyle", 539 | "clap_lex", 540 | "strsim", 541 | "terminal_size", 542 | ] 543 | 544 | [[package]] 545 | name = "clap_derive" 546 | version = "4.5.24" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" 549 | dependencies = [ 550 | "heck", 551 | "proc-macro2", 552 | "quote", 553 | "syn", 554 | ] 555 | 556 | [[package]] 557 | name = "clap_lex" 558 | version = "0.7.4" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 561 | 562 | [[package]] 563 | name = "cmake" 564 | version = "0.1.54" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" 567 | dependencies = [ 568 | "cc", 569 | ] 570 | 571 | [[package]] 572 | name = "codepage" 573 | version = "0.1.2" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "48f68d061bc2828ae826206326e61251aca94c1e4a5305cf52d9138639c918b4" 576 | dependencies = [ 577 | "encoding_rs", 578 | ] 579 | 580 | [[package]] 581 | name = "colorchoice" 582 | version = "1.0.3" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 585 | 586 | [[package]] 587 | name = "console" 588 | version = "0.15.10" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" 591 | dependencies = [ 592 | "encode_unicode", 593 | "libc", 594 | "once_cell", 595 | "unicode-width 0.2.0", 596 | "windows-sys 0.59.0", 597 | ] 598 | 599 | [[package]] 600 | name = "const_format" 601 | version = "0.2.34" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" 604 | dependencies = [ 605 | "const_format_proc_macros", 606 | ] 607 | 608 | [[package]] 609 | name = "const_format_proc_macros" 610 | version = "0.2.34" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" 613 | dependencies = [ 614 | "proc-macro2", 615 | "quote", 616 | "unicode-xid", 617 | ] 618 | 619 | [[package]] 620 | name = "core-foundation" 621 | version = "0.9.4" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 624 | dependencies = [ 625 | "core-foundation-sys", 626 | "libc", 627 | ] 628 | 629 | [[package]] 630 | name = "core-foundation-sys" 631 | version = "0.8.7" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 634 | 635 | [[package]] 636 | name = "cpufeatures" 637 | version = "0.2.17" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 640 | dependencies = [ 641 | "libc", 642 | ] 643 | 644 | [[package]] 645 | name = "crc32fast" 646 | version = "1.4.2" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 649 | dependencies = [ 650 | "cfg-if", 651 | ] 652 | 653 | [[package]] 654 | name = "crossbeam-channel" 655 | version = "0.5.14" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" 658 | dependencies = [ 659 | "crossbeam-utils", 660 | ] 661 | 662 | [[package]] 663 | name = "crossbeam-deque" 664 | version = "0.8.6" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 667 | dependencies = [ 668 | "crossbeam-epoch", 669 | "crossbeam-utils", 670 | ] 671 | 672 | [[package]] 673 | name = "crossbeam-epoch" 674 | version = "0.9.18" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 677 | dependencies = [ 678 | "crossbeam-utils", 679 | ] 680 | 681 | [[package]] 682 | name = "crossbeam-utils" 683 | version = "0.8.21" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 686 | 687 | [[package]] 688 | name = "crossterm" 689 | version = "0.28.1" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" 692 | dependencies = [ 693 | "bitflags 2.8.0", 694 | "crossterm_winapi", 695 | "mio 1.0.3", 696 | "parking_lot", 697 | "rustix", 698 | "serde", 699 | "signal-hook", 700 | "signal-hook-mio", 701 | "winapi", 702 | ] 703 | 704 | [[package]] 705 | name = "crossterm_winapi" 706 | version = "0.9.1" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 709 | dependencies = [ 710 | "winapi", 711 | ] 712 | 713 | [[package]] 714 | name = "crypto-common" 715 | version = "0.1.6" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 718 | dependencies = [ 719 | "generic-array", 720 | "typenum", 721 | ] 722 | 723 | [[package]] 724 | name = "csv" 725 | version = "1.3.1" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" 728 | dependencies = [ 729 | "csv-core", 730 | "itoa", 731 | "ryu", 732 | "serde", 733 | ] 734 | 735 | [[package]] 736 | name = "csv-core" 737 | version = "0.1.11" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" 740 | dependencies = [ 741 | "memchr", 742 | ] 743 | 744 | [[package]] 745 | name = "data-encoding" 746 | version = "2.8.0" 747 | source = "registry+https://github.com/rust-lang/crates.io-index" 748 | checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" 749 | 750 | [[package]] 751 | name = "deranged" 752 | version = "0.3.11" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 755 | dependencies = [ 756 | "powerfmt", 757 | ] 758 | 759 | [[package]] 760 | name = "derive_arbitrary" 761 | version = "1.4.1" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" 764 | dependencies = [ 765 | "proc-macro2", 766 | "quote", 767 | "syn", 768 | ] 769 | 770 | [[package]] 771 | name = "devicons" 772 | version = "0.6.12" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "830e47e2f330cf4fdd5a958dcef921b9523ffc21ab6713aa5e77ba2cce03904b" 775 | dependencies = [ 776 | "lazy_static", 777 | ] 778 | 779 | [[package]] 780 | name = "dialoguer" 781 | version = "0.11.0" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" 784 | dependencies = [ 785 | "console", 786 | "fuzzy-matcher", 787 | "shell-words", 788 | "thiserror 1.0.69", 789 | ] 790 | 791 | [[package]] 792 | name = "digest" 793 | version = "0.10.7" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 796 | dependencies = [ 797 | "block-buffer", 798 | "crypto-common", 799 | ] 800 | 801 | [[package]] 802 | name = "dirs" 803 | version = "5.0.1" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" 806 | dependencies = [ 807 | "dirs-sys", 808 | ] 809 | 810 | [[package]] 811 | name = "dirs-sys" 812 | version = "0.4.1" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" 815 | dependencies = [ 816 | "libc", 817 | "option-ext", 818 | "redox_users", 819 | "windows-sys 0.48.0", 820 | ] 821 | 822 | [[package]] 823 | name = "displaydoc" 824 | version = "0.2.5" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 827 | dependencies = [ 828 | "proc-macro2", 829 | "quote", 830 | "syn", 831 | ] 832 | 833 | [[package]] 834 | name = "dtparse" 835 | version = "2.0.1" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "23fb403c0926d35af2cc54d961bc2696a10d40725c08360ef69db04a4c201fd7" 838 | dependencies = [ 839 | "chrono", 840 | "lazy_static", 841 | "num-traits", 842 | "rust_decimal", 843 | ] 844 | 845 | [[package]] 846 | name = "dunce" 847 | version = "1.0.5" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" 850 | 851 | [[package]] 852 | name = "either" 853 | version = "1.13.0" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 856 | 857 | [[package]] 858 | name = "encode_unicode" 859 | version = "1.0.0" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" 862 | 863 | [[package]] 864 | name = "encoding_rs" 865 | version = "0.8.35" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 868 | dependencies = [ 869 | "cfg-if", 870 | ] 871 | 872 | [[package]] 873 | name = "env_home" 874 | version = "0.1.0" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" 877 | 878 | [[package]] 879 | name = "equivalent" 880 | version = "1.0.1" 881 | source = "registry+https://github.com/rust-lang/crates.io-index" 882 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 883 | 884 | [[package]] 885 | name = "erased-serde" 886 | version = "0.4.5" 887 | source = "registry+https://github.com/rust-lang/crates.io-index" 888 | checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" 889 | dependencies = [ 890 | "serde", 891 | "typeid", 892 | ] 893 | 894 | [[package]] 895 | name = "errno" 896 | version = "0.3.10" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" 899 | dependencies = [ 900 | "libc", 901 | "windows-sys 0.59.0", 902 | ] 903 | 904 | [[package]] 905 | name = "etcetera" 906 | version = "0.8.0" 907 | source = "registry+https://github.com/rust-lang/crates.io-index" 908 | checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 909 | dependencies = [ 910 | "cfg-if", 911 | "home", 912 | "windows-sys 0.48.0", 913 | ] 914 | 915 | [[package]] 916 | name = "fallible-iterator" 917 | version = "0.3.0" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" 920 | 921 | [[package]] 922 | name = "fallible-streaming-iterator" 923 | version = "0.1.9" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 926 | 927 | [[package]] 928 | name = "fancy-regex" 929 | version = "0.14.0" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" 932 | dependencies = [ 933 | "bit-set", 934 | "regex-automata", 935 | "regex-syntax", 936 | ] 937 | 938 | [[package]] 939 | name = "fastrand" 940 | version = "2.3.0" 941 | source = "registry+https://github.com/rust-lang/crates.io-index" 942 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 943 | 944 | [[package]] 945 | name = "fd-lock" 946 | version = "4.0.2" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" 949 | dependencies = [ 950 | "cfg-if", 951 | "rustix", 952 | "windows-sys 0.52.0", 953 | ] 954 | 955 | [[package]] 956 | name = "file-id" 957 | version = "0.2.2" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "6bc904b9bbefcadbd8e3a9fb0d464a9b979de6324c03b3c663e8994f46a5be36" 960 | dependencies = [ 961 | "windows-sys 0.52.0", 962 | ] 963 | 964 | [[package]] 965 | name = "filesize" 966 | version = "0.2.0" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "12d741e2415d4e2e5bd1c1d00409d1a8865a57892c2d689b504365655d237d43" 969 | dependencies = [ 970 | "winapi", 971 | ] 972 | 973 | [[package]] 974 | name = "filetime" 975 | version = "0.2.25" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" 978 | dependencies = [ 979 | "cfg-if", 980 | "libc", 981 | "libredox", 982 | "windows-sys 0.59.0", 983 | ] 984 | 985 | [[package]] 986 | name = "flate2" 987 | version = "1.0.35" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" 990 | dependencies = [ 991 | "crc32fast", 992 | "miniz_oxide", 993 | ] 994 | 995 | [[package]] 996 | name = "fnv" 997 | version = "1.0.7" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 1000 | 1001 | [[package]] 1002 | name = "foldhash" 1003 | version = "0.1.4" 1004 | source = "registry+https://github.com/rust-lang/crates.io-index" 1005 | checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" 1006 | 1007 | [[package]] 1008 | name = "foreign-types" 1009 | version = "0.3.2" 1010 | source = "registry+https://github.com/rust-lang/crates.io-index" 1011 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 1012 | dependencies = [ 1013 | "foreign-types-shared", 1014 | ] 1015 | 1016 | [[package]] 1017 | name = "foreign-types-shared" 1018 | version = "0.1.1" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 1021 | 1022 | [[package]] 1023 | name = "form_urlencoded" 1024 | version = "1.2.1" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 1027 | dependencies = [ 1028 | "percent-encoding", 1029 | ] 1030 | 1031 | [[package]] 1032 | name = "fs_extra" 1033 | version = "1.3.0" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" 1036 | 1037 | [[package]] 1038 | name = "fsevent-sys" 1039 | version = "4.1.0" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" 1042 | dependencies = [ 1043 | "libc", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "fstr" 1048 | version = "0.2.12" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "59fd8999da11407ccf70cbe696eb7f819b85429d83ee3c6eb2f514b1751d246b" 1051 | 1052 | [[package]] 1053 | name = "futures-channel" 1054 | version = "0.3.31" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 1057 | dependencies = [ 1058 | "futures-core", 1059 | "futures-sink", 1060 | ] 1061 | 1062 | [[package]] 1063 | name = "futures-core" 1064 | version = "0.3.31" 1065 | source = "registry+https://github.com/rust-lang/crates.io-index" 1066 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 1067 | 1068 | [[package]] 1069 | name = "futures-io" 1070 | version = "0.3.31" 1071 | source = "registry+https://github.com/rust-lang/crates.io-index" 1072 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 1073 | 1074 | [[package]] 1075 | name = "futures-macro" 1076 | version = "0.3.31" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 1079 | dependencies = [ 1080 | "proc-macro2", 1081 | "quote", 1082 | "syn", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "futures-sink" 1087 | version = "0.3.31" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 1090 | 1091 | [[package]] 1092 | name = "futures-task" 1093 | version = "0.3.31" 1094 | source = "registry+https://github.com/rust-lang/crates.io-index" 1095 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 1096 | 1097 | [[package]] 1098 | name = "futures-util" 1099 | version = "0.3.31" 1100 | source = "registry+https://github.com/rust-lang/crates.io-index" 1101 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 1102 | dependencies = [ 1103 | "futures-core", 1104 | "futures-io", 1105 | "futures-macro", 1106 | "futures-sink", 1107 | "futures-task", 1108 | "memchr", 1109 | "pin-project-lite", 1110 | "pin-utils", 1111 | "slab", 1112 | ] 1113 | 1114 | [[package]] 1115 | name = "fuzzy-matcher" 1116 | version = "0.3.7" 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" 1118 | checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" 1119 | dependencies = [ 1120 | "thread_local", 1121 | ] 1122 | 1123 | [[package]] 1124 | name = "generic-array" 1125 | version = "0.14.7" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 1128 | dependencies = [ 1129 | "typenum", 1130 | "version_check", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "getrandom" 1135 | version = "0.2.15" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 1138 | dependencies = [ 1139 | "cfg-if", 1140 | "js-sys", 1141 | "libc", 1142 | "wasi 0.11.0+wasi-snapshot-preview1", 1143 | "wasm-bindgen", 1144 | ] 1145 | 1146 | [[package]] 1147 | name = "getrandom" 1148 | version = "0.3.1" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" 1151 | dependencies = [ 1152 | "cfg-if", 1153 | "libc", 1154 | "wasi 0.13.3+wasi-0.2.2", 1155 | "windows-targets 0.52.6", 1156 | ] 1157 | 1158 | [[package]] 1159 | name = "gimli" 1160 | version = "0.31.1" 1161 | source = "registry+https://github.com/rust-lang/crates.io-index" 1162 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 1163 | 1164 | [[package]] 1165 | name = "glob" 1166 | version = "0.3.2" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" 1169 | 1170 | [[package]] 1171 | name = "h2" 1172 | version = "0.4.7" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" 1175 | dependencies = [ 1176 | "atomic-waker", 1177 | "bytes", 1178 | "fnv", 1179 | "futures-core", 1180 | "futures-sink", 1181 | "http", 1182 | "indexmap", 1183 | "slab", 1184 | "tokio", 1185 | "tokio-util", 1186 | "tracing", 1187 | ] 1188 | 1189 | [[package]] 1190 | name = "hashbrown" 1191 | version = "0.14.5" 1192 | source = "registry+https://github.com/rust-lang/crates.io-index" 1193 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1194 | dependencies = [ 1195 | "ahash", 1196 | ] 1197 | 1198 | [[package]] 1199 | name = "hashbrown" 1200 | version = "0.15.2" 1201 | source = "registry+https://github.com/rust-lang/crates.io-index" 1202 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 1203 | dependencies = [ 1204 | "allocator-api2", 1205 | "equivalent", 1206 | "foldhash", 1207 | ] 1208 | 1209 | [[package]] 1210 | name = "hashlink" 1211 | version = "0.9.1" 1212 | source = "registry+https://github.com/rust-lang/crates.io-index" 1213 | checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" 1214 | dependencies = [ 1215 | "hashbrown 0.14.5", 1216 | ] 1217 | 1218 | [[package]] 1219 | name = "heck" 1220 | version = "0.5.0" 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" 1222 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 1223 | 1224 | [[package]] 1225 | name = "hex" 1226 | version = "0.4.3" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1229 | 1230 | [[package]] 1231 | name = "home" 1232 | version = "0.5.11" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 1235 | dependencies = [ 1236 | "windows-sys 0.59.0", 1237 | ] 1238 | 1239 | [[package]] 1240 | name = "http" 1241 | version = "1.2.0" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" 1244 | dependencies = [ 1245 | "bytes", 1246 | "fnv", 1247 | "itoa", 1248 | ] 1249 | 1250 | [[package]] 1251 | name = "http-body" 1252 | version = "1.0.1" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 1255 | dependencies = [ 1256 | "bytes", 1257 | "http", 1258 | ] 1259 | 1260 | [[package]] 1261 | name = "http-body-util" 1262 | version = "0.1.2" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 1265 | dependencies = [ 1266 | "bytes", 1267 | "futures-util", 1268 | "http", 1269 | "http-body", 1270 | "pin-project-lite", 1271 | ] 1272 | 1273 | [[package]] 1274 | name = "http-nu" 1275 | version = "0.4.2" 1276 | dependencies = [ 1277 | "bytes", 1278 | "clap", 1279 | "http", 1280 | "http-body-util", 1281 | "http-serde", 1282 | "hyper", 1283 | "hyper-staticfile", 1284 | "hyper-util", 1285 | "nu-cli", 1286 | "nu-cmd-extra", 1287 | "nu-cmd-lang", 1288 | "nu-command", 1289 | "nu-engine", 1290 | "nu-parser", 1291 | "nu-protocol", 1292 | "rustls", 1293 | "rustls-pemfile", 1294 | "scru128", 1295 | "serde", 1296 | "serde_json", 1297 | "tempfile", 1298 | "tokio", 1299 | "tokio-rustls", 1300 | "tokio-stream", 1301 | "tokio-test", 1302 | "tokio-util", 1303 | "url", 1304 | ] 1305 | 1306 | [[package]] 1307 | name = "http-range" 1308 | version = "0.1.5" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" 1311 | 1312 | [[package]] 1313 | name = "http-serde" 1314 | version = "2.1.1" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "0f056c8559e3757392c8d091e796416e4649d8e49e88b8d76df6c002f05027fd" 1317 | dependencies = [ 1318 | "http", 1319 | "serde", 1320 | ] 1321 | 1322 | [[package]] 1323 | name = "httparse" 1324 | version = "1.9.5" 1325 | source = "registry+https://github.com/rust-lang/crates.io-index" 1326 | checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" 1327 | 1328 | [[package]] 1329 | name = "httpdate" 1330 | version = "1.0.3" 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" 1332 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 1333 | 1334 | [[package]] 1335 | name = "human-date-parser" 1336 | version = "0.2.0" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "1116cf4debfe770c12168458321c4a8591b71c4c19f7100de07c84cf81701c63" 1339 | dependencies = [ 1340 | "chrono", 1341 | "pest", 1342 | "pest_derive", 1343 | "thiserror 1.0.69", 1344 | ] 1345 | 1346 | [[package]] 1347 | name = "hyper" 1348 | version = "1.5.2" 1349 | source = "registry+https://github.com/rust-lang/crates.io-index" 1350 | checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" 1351 | dependencies = [ 1352 | "bytes", 1353 | "futures-channel", 1354 | "futures-util", 1355 | "h2", 1356 | "http", 1357 | "http-body", 1358 | "httparse", 1359 | "httpdate", 1360 | "itoa", 1361 | "pin-project-lite", 1362 | "smallvec", 1363 | "tokio", 1364 | "want", 1365 | ] 1366 | 1367 | [[package]] 1368 | name = "hyper-staticfile" 1369 | version = "0.10.1" 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" 1371 | checksum = "bc4bce64c32578957926e75f832032f81ebb30bcee74f86c5848b13a69e547eb" 1372 | dependencies = [ 1373 | "futures-util", 1374 | "http", 1375 | "http-range", 1376 | "httpdate", 1377 | "hyper", 1378 | "mime_guess", 1379 | "percent-encoding", 1380 | "rand", 1381 | "tokio", 1382 | "url", 1383 | "winapi", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "hyper-tls" 1388 | version = "0.6.0" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 1391 | dependencies = [ 1392 | "bytes", 1393 | "http-body-util", 1394 | "hyper", 1395 | "hyper-util", 1396 | "native-tls", 1397 | "tokio", 1398 | "tokio-native-tls", 1399 | "tower-service", 1400 | ] 1401 | 1402 | [[package]] 1403 | name = "hyper-util" 1404 | version = "0.1.10" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" 1407 | dependencies = [ 1408 | "bytes", 1409 | "futures-channel", 1410 | "futures-util", 1411 | "http", 1412 | "http-body", 1413 | "hyper", 1414 | "pin-project-lite", 1415 | "socket2", 1416 | "tokio", 1417 | "tower-service", 1418 | "tracing", 1419 | ] 1420 | 1421 | [[package]] 1422 | name = "iana-time-zone" 1423 | version = "0.1.61" 1424 | source = "registry+https://github.com/rust-lang/crates.io-index" 1425 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 1426 | dependencies = [ 1427 | "android_system_properties", 1428 | "core-foundation-sys", 1429 | "iana-time-zone-haiku", 1430 | "js-sys", 1431 | "wasm-bindgen", 1432 | "windows-core 0.52.0", 1433 | ] 1434 | 1435 | [[package]] 1436 | name = "iana-time-zone-haiku" 1437 | version = "0.1.2" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1440 | dependencies = [ 1441 | "cc", 1442 | ] 1443 | 1444 | [[package]] 1445 | name = "icu_collections" 1446 | version = "1.5.0" 1447 | source = "registry+https://github.com/rust-lang/crates.io-index" 1448 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 1449 | dependencies = [ 1450 | "displaydoc", 1451 | "yoke", 1452 | "zerofrom", 1453 | "zerovec", 1454 | ] 1455 | 1456 | [[package]] 1457 | name = "icu_locid" 1458 | version = "1.5.0" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 1461 | dependencies = [ 1462 | "displaydoc", 1463 | "litemap", 1464 | "tinystr", 1465 | "writeable", 1466 | "zerovec", 1467 | ] 1468 | 1469 | [[package]] 1470 | name = "icu_locid_transform" 1471 | version = "1.5.0" 1472 | source = "registry+https://github.com/rust-lang/crates.io-index" 1473 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 1474 | dependencies = [ 1475 | "displaydoc", 1476 | "icu_locid", 1477 | "icu_locid_transform_data", 1478 | "icu_provider", 1479 | "tinystr", 1480 | "zerovec", 1481 | ] 1482 | 1483 | [[package]] 1484 | name = "icu_locid_transform_data" 1485 | version = "1.5.0" 1486 | source = "registry+https://github.com/rust-lang/crates.io-index" 1487 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 1488 | 1489 | [[package]] 1490 | name = "icu_normalizer" 1491 | version = "1.5.0" 1492 | source = "registry+https://github.com/rust-lang/crates.io-index" 1493 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 1494 | dependencies = [ 1495 | "displaydoc", 1496 | "icu_collections", 1497 | "icu_normalizer_data", 1498 | "icu_properties", 1499 | "icu_provider", 1500 | "smallvec", 1501 | "utf16_iter", 1502 | "utf8_iter", 1503 | "write16", 1504 | "zerovec", 1505 | ] 1506 | 1507 | [[package]] 1508 | name = "icu_normalizer_data" 1509 | version = "1.5.0" 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" 1511 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 1512 | 1513 | [[package]] 1514 | name = "icu_properties" 1515 | version = "1.5.1" 1516 | source = "registry+https://github.com/rust-lang/crates.io-index" 1517 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 1518 | dependencies = [ 1519 | "displaydoc", 1520 | "icu_collections", 1521 | "icu_locid_transform", 1522 | "icu_properties_data", 1523 | "icu_provider", 1524 | "tinystr", 1525 | "zerovec", 1526 | ] 1527 | 1528 | [[package]] 1529 | name = "icu_properties_data" 1530 | version = "1.5.0" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 1533 | 1534 | [[package]] 1535 | name = "icu_provider" 1536 | version = "1.5.0" 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" 1538 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 1539 | dependencies = [ 1540 | "displaydoc", 1541 | "icu_locid", 1542 | "icu_provider_macros", 1543 | "stable_deref_trait", 1544 | "tinystr", 1545 | "writeable", 1546 | "yoke", 1547 | "zerofrom", 1548 | "zerovec", 1549 | ] 1550 | 1551 | [[package]] 1552 | name = "icu_provider_macros" 1553 | version = "1.5.0" 1554 | source = "registry+https://github.com/rust-lang/crates.io-index" 1555 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 1556 | dependencies = [ 1557 | "proc-macro2", 1558 | "quote", 1559 | "syn", 1560 | ] 1561 | 1562 | [[package]] 1563 | name = "idna" 1564 | version = "1.0.3" 1565 | source = "registry+https://github.com/rust-lang/crates.io-index" 1566 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1567 | dependencies = [ 1568 | "idna_adapter", 1569 | "smallvec", 1570 | "utf8_iter", 1571 | ] 1572 | 1573 | [[package]] 1574 | name = "idna_adapter" 1575 | version = "1.2.0" 1576 | source = "registry+https://github.com/rust-lang/crates.io-index" 1577 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 1578 | dependencies = [ 1579 | "icu_normalizer", 1580 | "icu_properties", 1581 | ] 1582 | 1583 | [[package]] 1584 | name = "indexmap" 1585 | version = "2.7.1" 1586 | source = "registry+https://github.com/rust-lang/crates.io-index" 1587 | checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" 1588 | dependencies = [ 1589 | "equivalent", 1590 | "hashbrown 0.15.2", 1591 | ] 1592 | 1593 | [[package]] 1594 | name = "indicatif" 1595 | version = "0.17.11" 1596 | source = "registry+https://github.com/rust-lang/crates.io-index" 1597 | checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" 1598 | dependencies = [ 1599 | "console", 1600 | "number_prefix", 1601 | "portable-atomic", 1602 | "unicode-width 0.2.0", 1603 | "web-time", 1604 | ] 1605 | 1606 | [[package]] 1607 | name = "inotify" 1608 | version = "0.9.6" 1609 | source = "registry+https://github.com/rust-lang/crates.io-index" 1610 | checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" 1611 | dependencies = [ 1612 | "bitflags 1.3.2", 1613 | "inotify-sys", 1614 | "libc", 1615 | ] 1616 | 1617 | [[package]] 1618 | name = "inotify-sys" 1619 | version = "0.1.5" 1620 | source = "registry+https://github.com/rust-lang/crates.io-index" 1621 | checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" 1622 | dependencies = [ 1623 | "libc", 1624 | ] 1625 | 1626 | [[package]] 1627 | name = "inventory" 1628 | version = "0.3.17" 1629 | source = "registry+https://github.com/rust-lang/crates.io-index" 1630 | checksum = "3b31349d02fe60f80bbbab1a9402364cad7460626d6030494b08ac4a2075bf81" 1631 | dependencies = [ 1632 | "rustversion", 1633 | ] 1634 | 1635 | [[package]] 1636 | name = "ipnet" 1637 | version = "2.11.0" 1638 | source = "registry+https://github.com/rust-lang/crates.io-index" 1639 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1640 | 1641 | [[package]] 1642 | name = "is-docker" 1643 | version = "0.2.0" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" 1646 | dependencies = [ 1647 | "once_cell", 1648 | ] 1649 | 1650 | [[package]] 1651 | name = "is-wsl" 1652 | version = "0.4.0" 1653 | source = "registry+https://github.com/rust-lang/crates.io-index" 1654 | checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" 1655 | dependencies = [ 1656 | "is-docker", 1657 | "once_cell", 1658 | ] 1659 | 1660 | [[package]] 1661 | name = "is_ci" 1662 | version = "1.2.0" 1663 | source = "registry+https://github.com/rust-lang/crates.io-index" 1664 | checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" 1665 | 1666 | [[package]] 1667 | name = "is_debug" 1668 | version = "1.0.2" 1669 | source = "registry+https://github.com/rust-lang/crates.io-index" 1670 | checksum = "e8ea828c9d6638a5bd3d8b14e37502b4d56cae910ccf8a5b7f51c7a0eb1d0508" 1671 | 1672 | [[package]] 1673 | name = "is_executable" 1674 | version = "1.0.4" 1675 | source = "registry+https://github.com/rust-lang/crates.io-index" 1676 | checksum = "d4a1b5bad6f9072935961dfbf1cced2f3d129963d091b6f69f007fe04e758ae2" 1677 | dependencies = [ 1678 | "winapi", 1679 | ] 1680 | 1681 | [[package]] 1682 | name = "is_terminal_polyfill" 1683 | version = "1.70.1" 1684 | source = "registry+https://github.com/rust-lang/crates.io-index" 1685 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1686 | 1687 | [[package]] 1688 | name = "itertools" 1689 | version = "0.11.0" 1690 | source = "registry+https://github.com/rust-lang/crates.io-index" 1691 | checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" 1692 | dependencies = [ 1693 | "either", 1694 | ] 1695 | 1696 | [[package]] 1697 | name = "itertools" 1698 | version = "0.12.1" 1699 | source = "registry+https://github.com/rust-lang/crates.io-index" 1700 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 1701 | dependencies = [ 1702 | "either", 1703 | ] 1704 | 1705 | [[package]] 1706 | name = "itertools" 1707 | version = "0.13.0" 1708 | source = "registry+https://github.com/rust-lang/crates.io-index" 1709 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 1710 | dependencies = [ 1711 | "either", 1712 | ] 1713 | 1714 | [[package]] 1715 | name = "itoa" 1716 | version = "1.0.14" 1717 | source = "registry+https://github.com/rust-lang/crates.io-index" 1718 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 1719 | 1720 | [[package]] 1721 | name = "jobserver" 1722 | version = "0.1.32" 1723 | source = "registry+https://github.com/rust-lang/crates.io-index" 1724 | checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" 1725 | dependencies = [ 1726 | "libc", 1727 | ] 1728 | 1729 | [[package]] 1730 | name = "js-sys" 1731 | version = "0.3.77" 1732 | source = "registry+https://github.com/rust-lang/crates.io-index" 1733 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 1734 | dependencies = [ 1735 | "once_cell", 1736 | "wasm-bindgen", 1737 | ] 1738 | 1739 | [[package]] 1740 | name = "kqueue" 1741 | version = "1.0.8" 1742 | source = "registry+https://github.com/rust-lang/crates.io-index" 1743 | checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" 1744 | dependencies = [ 1745 | "kqueue-sys", 1746 | "libc", 1747 | ] 1748 | 1749 | [[package]] 1750 | name = "kqueue-sys" 1751 | version = "1.0.4" 1752 | source = "registry+https://github.com/rust-lang/crates.io-index" 1753 | checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" 1754 | dependencies = [ 1755 | "bitflags 1.3.2", 1756 | "libc", 1757 | ] 1758 | 1759 | [[package]] 1760 | name = "lazy_static" 1761 | version = "1.5.0" 1762 | source = "registry+https://github.com/rust-lang/crates.io-index" 1763 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1764 | 1765 | [[package]] 1766 | name = "lazycell" 1767 | version = "1.3.0" 1768 | source = "registry+https://github.com/rust-lang/crates.io-index" 1769 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 1770 | 1771 | [[package]] 1772 | name = "libc" 1773 | version = "0.2.169" 1774 | source = "registry+https://github.com/rust-lang/crates.io-index" 1775 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 1776 | 1777 | [[package]] 1778 | name = "libloading" 1779 | version = "0.8.6" 1780 | source = "registry+https://github.com/rust-lang/crates.io-index" 1781 | checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" 1782 | dependencies = [ 1783 | "cfg-if", 1784 | "windows-targets 0.52.6", 1785 | ] 1786 | 1787 | [[package]] 1788 | name = "libproc" 1789 | version = "0.14.10" 1790 | source = "registry+https://github.com/rust-lang/crates.io-index" 1791 | checksum = "e78a09b56be5adbcad5aa1197371688dc6bb249a26da3bca2011ee2fb987ebfb" 1792 | dependencies = [ 1793 | "bindgen 0.70.1", 1794 | "errno", 1795 | "libc", 1796 | ] 1797 | 1798 | [[package]] 1799 | name = "libredox" 1800 | version = "0.1.3" 1801 | source = "registry+https://github.com/rust-lang/crates.io-index" 1802 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 1803 | dependencies = [ 1804 | "bitflags 2.8.0", 1805 | "libc", 1806 | "redox_syscall", 1807 | ] 1808 | 1809 | [[package]] 1810 | name = "libsqlite3-sys" 1811 | version = "0.28.0" 1812 | source = "registry+https://github.com/rust-lang/crates.io-index" 1813 | checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" 1814 | dependencies = [ 1815 | "cc", 1816 | "pkg-config", 1817 | "vcpkg", 1818 | ] 1819 | 1820 | [[package]] 1821 | name = "linked-hash-map" 1822 | version = "0.5.6" 1823 | source = "registry+https://github.com/rust-lang/crates.io-index" 1824 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" 1825 | dependencies = [ 1826 | "serde", 1827 | ] 1828 | 1829 | [[package]] 1830 | name = "linux-raw-sys" 1831 | version = "0.4.15" 1832 | source = "registry+https://github.com/rust-lang/crates.io-index" 1833 | checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 1834 | 1835 | [[package]] 1836 | name = "litemap" 1837 | version = "0.7.4" 1838 | source = "registry+https://github.com/rust-lang/crates.io-index" 1839 | checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" 1840 | 1841 | [[package]] 1842 | name = "lock_api" 1843 | version = "0.4.12" 1844 | source = "registry+https://github.com/rust-lang/crates.io-index" 1845 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1846 | dependencies = [ 1847 | "autocfg", 1848 | "scopeguard", 1849 | ] 1850 | 1851 | [[package]] 1852 | name = "lockfree-object-pool" 1853 | version = "0.1.6" 1854 | source = "registry+https://github.com/rust-lang/crates.io-index" 1855 | checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" 1856 | 1857 | [[package]] 1858 | name = "log" 1859 | version = "0.4.25" 1860 | source = "registry+https://github.com/rust-lang/crates.io-index" 1861 | checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" 1862 | 1863 | [[package]] 1864 | name = "lru" 1865 | version = "0.12.5" 1866 | source = "registry+https://github.com/rust-lang/crates.io-index" 1867 | checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" 1868 | dependencies = [ 1869 | "hashbrown 0.15.2", 1870 | ] 1871 | 1872 | [[package]] 1873 | name = "lscolors" 1874 | version = "0.17.0" 1875 | source = "registry+https://github.com/rust-lang/crates.io-index" 1876 | checksum = "53304fff6ab1e597661eee37e42ea8c47a146fca280af902bb76bff8a896e523" 1877 | dependencies = [ 1878 | "nu-ansi-term", 1879 | ] 1880 | 1881 | [[package]] 1882 | name = "mach2" 1883 | version = "0.4.2" 1884 | source = "registry+https://github.com/rust-lang/crates.io-index" 1885 | checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" 1886 | dependencies = [ 1887 | "libc", 1888 | ] 1889 | 1890 | [[package]] 1891 | name = "md-5" 1892 | version = "0.10.6" 1893 | source = "registry+https://github.com/rust-lang/crates.io-index" 1894 | checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1895 | dependencies = [ 1896 | "cfg-if", 1897 | "digest", 1898 | ] 1899 | 1900 | [[package]] 1901 | name = "memchr" 1902 | version = "2.7.4" 1903 | source = "registry+https://github.com/rust-lang/crates.io-index" 1904 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1905 | 1906 | [[package]] 1907 | name = "miette" 1908 | version = "7.5.0" 1909 | source = "registry+https://github.com/rust-lang/crates.io-index" 1910 | checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484" 1911 | dependencies = [ 1912 | "cfg-if", 1913 | "miette-derive", 1914 | "owo-colors", 1915 | "supports-color", 1916 | "supports-hyperlinks", 1917 | "supports-unicode", 1918 | "terminal_size", 1919 | "textwrap", 1920 | "thiserror 1.0.69", 1921 | "unicode-width 0.1.11", 1922 | ] 1923 | 1924 | [[package]] 1925 | name = "miette-derive" 1926 | version = "7.5.0" 1927 | source = "registry+https://github.com/rust-lang/crates.io-index" 1928 | checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147" 1929 | dependencies = [ 1930 | "proc-macro2", 1931 | "quote", 1932 | "syn", 1933 | ] 1934 | 1935 | [[package]] 1936 | name = "mime" 1937 | version = "0.3.17" 1938 | source = "registry+https://github.com/rust-lang/crates.io-index" 1939 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1940 | 1941 | [[package]] 1942 | name = "mime_guess" 1943 | version = "2.0.5" 1944 | source = "registry+https://github.com/rust-lang/crates.io-index" 1945 | checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 1946 | dependencies = [ 1947 | "mime", 1948 | "unicase", 1949 | ] 1950 | 1951 | [[package]] 1952 | name = "minimal-lexical" 1953 | version = "0.2.1" 1954 | source = "registry+https://github.com/rust-lang/crates.io-index" 1955 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1956 | 1957 | [[package]] 1958 | name = "miniz_oxide" 1959 | version = "0.8.3" 1960 | source = "registry+https://github.com/rust-lang/crates.io-index" 1961 | checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" 1962 | dependencies = [ 1963 | "adler2", 1964 | ] 1965 | 1966 | [[package]] 1967 | name = "mio" 1968 | version = "0.8.11" 1969 | source = "registry+https://github.com/rust-lang/crates.io-index" 1970 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 1971 | dependencies = [ 1972 | "libc", 1973 | "log", 1974 | "wasi 0.11.0+wasi-snapshot-preview1", 1975 | "windows-sys 0.48.0", 1976 | ] 1977 | 1978 | [[package]] 1979 | name = "mio" 1980 | version = "1.0.3" 1981 | source = "registry+https://github.com/rust-lang/crates.io-index" 1982 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 1983 | dependencies = [ 1984 | "libc", 1985 | "log", 1986 | "wasi 0.11.0+wasi-snapshot-preview1", 1987 | "windows-sys 0.52.0", 1988 | ] 1989 | 1990 | [[package]] 1991 | name = "multipart-rs" 1992 | version = "0.1.13" 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" 1994 | checksum = "64cae00e7e52aa5072342ef9a2ccd71669be913c2176a81a665b1f9cd79345f2" 1995 | dependencies = [ 1996 | "bytes", 1997 | "futures-core", 1998 | "futures-util", 1999 | "memchr", 2000 | "mime", 2001 | "uuid", 2002 | ] 2003 | 2004 | [[package]] 2005 | name = "native-tls" 2006 | version = "0.2.13" 2007 | source = "registry+https://github.com/rust-lang/crates.io-index" 2008 | checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" 2009 | dependencies = [ 2010 | "libc", 2011 | "log", 2012 | "openssl", 2013 | "openssl-probe", 2014 | "openssl-sys", 2015 | "schannel", 2016 | "security-framework", 2017 | "security-framework-sys", 2018 | "tempfile", 2019 | ] 2020 | 2021 | [[package]] 2022 | name = "nix" 2023 | version = "0.29.0" 2024 | source = "registry+https://github.com/rust-lang/crates.io-index" 2025 | checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" 2026 | dependencies = [ 2027 | "bitflags 2.8.0", 2028 | "cfg-if", 2029 | "cfg_aliases", 2030 | "libc", 2031 | ] 2032 | 2033 | [[package]] 2034 | name = "nom" 2035 | version = "7.1.3" 2036 | source = "registry+https://github.com/rust-lang/crates.io-index" 2037 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 2038 | dependencies = [ 2039 | "memchr", 2040 | "minimal-lexical", 2041 | ] 2042 | 2043 | [[package]] 2044 | name = "notify" 2045 | version = "6.1.1" 2046 | source = "registry+https://github.com/rust-lang/crates.io-index" 2047 | checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" 2048 | dependencies = [ 2049 | "bitflags 2.8.0", 2050 | "crossbeam-channel", 2051 | "filetime", 2052 | "fsevent-sys", 2053 | "inotify", 2054 | "kqueue", 2055 | "libc", 2056 | "log", 2057 | "mio 0.8.11", 2058 | "walkdir", 2059 | "windows-sys 0.48.0", 2060 | ] 2061 | 2062 | [[package]] 2063 | name = "notify-debouncer-full" 2064 | version = "0.3.2" 2065 | source = "registry+https://github.com/rust-lang/crates.io-index" 2066 | checksum = "fb7fd166739789c9ff169e654dc1501373db9d80a4c3f972817c8a4d7cf8f34e" 2067 | dependencies = [ 2068 | "file-id", 2069 | "log", 2070 | "notify", 2071 | "parking_lot", 2072 | "walkdir", 2073 | ] 2074 | 2075 | [[package]] 2076 | name = "ntapi" 2077 | version = "0.4.1" 2078 | source = "registry+https://github.com/rust-lang/crates.io-index" 2079 | checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" 2080 | dependencies = [ 2081 | "winapi", 2082 | ] 2083 | 2084 | [[package]] 2085 | name = "nu-ansi-term" 2086 | version = "0.50.1" 2087 | source = "registry+https://github.com/rust-lang/crates.io-index" 2088 | checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" 2089 | dependencies = [ 2090 | "windows-sys 0.52.0", 2091 | ] 2092 | 2093 | [[package]] 2094 | name = "nu-cli" 2095 | version = "0.103.0" 2096 | source = "registry+https://github.com/rust-lang/crates.io-index" 2097 | checksum = "ffbdb07700d7e1e8d54b104ec4448c057c5371e123ea3ccbcce66b3482c3ee70" 2098 | dependencies = [ 2099 | "chrono", 2100 | "crossterm", 2101 | "fancy-regex", 2102 | "is_executable", 2103 | "log", 2104 | "lscolors", 2105 | "miette", 2106 | "nu-ansi-term", 2107 | "nu-cmd-base", 2108 | "nu-color-config", 2109 | "nu-engine", 2110 | "nu-glob", 2111 | "nu-parser", 2112 | "nu-path", 2113 | "nu-protocol", 2114 | "nu-utils", 2115 | "nucleo-matcher", 2116 | "percent-encoding", 2117 | "reedline", 2118 | "strum", 2119 | "sysinfo", 2120 | "unicode-segmentation", 2121 | "uuid", 2122 | "which 7.0.1", 2123 | ] 2124 | 2125 | [[package]] 2126 | name = "nu-cmd-base" 2127 | version = "0.103.0" 2128 | source = "registry+https://github.com/rust-lang/crates.io-index" 2129 | checksum = "b5e3fadfe7bf3383778c596df0bd11c166e8c363aa64133269c0ff695086c1d2" 2130 | dependencies = [ 2131 | "indexmap", 2132 | "miette", 2133 | "nu-engine", 2134 | "nu-parser", 2135 | "nu-path", 2136 | "nu-protocol", 2137 | ] 2138 | 2139 | [[package]] 2140 | name = "nu-cmd-extra" 2141 | version = "0.103.0" 2142 | source = "registry+https://github.com/rust-lang/crates.io-index" 2143 | checksum = "e26ba6b42ee4463a62825fc4bf899086426721cdddb441c540fa35cd9ef2b4e9" 2144 | dependencies = [ 2145 | "fancy-regex", 2146 | "heck", 2147 | "itertools 0.13.0", 2148 | "mime", 2149 | "nu-ansi-term", 2150 | "nu-cmd-base", 2151 | "nu-engine", 2152 | "nu-json", 2153 | "nu-parser", 2154 | "nu-pretty-hex", 2155 | "nu-protocol", 2156 | "nu-utils", 2157 | "num-traits", 2158 | "rust-embed", 2159 | "serde", 2160 | "serde_urlencoded", 2161 | "v_htmlescape", 2162 | ] 2163 | 2164 | [[package]] 2165 | name = "nu-cmd-lang" 2166 | version = "0.103.0" 2167 | source = "registry+https://github.com/rust-lang/crates.io-index" 2168 | checksum = "8cea93e3f189c944a246221d7c8ed8e57b23379bf9bb0d31ea7964ff2b56020d" 2169 | dependencies = [ 2170 | "itertools 0.13.0", 2171 | "nu-engine", 2172 | "nu-parser", 2173 | "nu-protocol", 2174 | "nu-utils", 2175 | "shadow-rs", 2176 | ] 2177 | 2178 | [[package]] 2179 | name = "nu-color-config" 2180 | version = "0.103.0" 2181 | source = "registry+https://github.com/rust-lang/crates.io-index" 2182 | checksum = "bd3638911ec37bc7393abce308d45a8e3f0c35d74f55fbe1029b7a8e9edc6322" 2183 | dependencies = [ 2184 | "nu-ansi-term", 2185 | "nu-engine", 2186 | "nu-json", 2187 | "nu-protocol", 2188 | "serde", 2189 | ] 2190 | 2191 | [[package]] 2192 | name = "nu-command" 2193 | version = "0.103.0" 2194 | source = "registry+https://github.com/rust-lang/crates.io-index" 2195 | checksum = "9e5514fc30fa130b9f36efeddc5725153b4bb0ace265b8e216db20690682d7ec" 2196 | dependencies = [ 2197 | "alphanumeric-sort", 2198 | "base64", 2199 | "bracoxide", 2200 | "brotli", 2201 | "byteorder", 2202 | "bytesize", 2203 | "calamine", 2204 | "chardetng", 2205 | "chrono", 2206 | "chrono-humanize", 2207 | "chrono-tz", 2208 | "crossterm", 2209 | "csv", 2210 | "data-encoding", 2211 | "devicons", 2212 | "dialoguer", 2213 | "digest", 2214 | "dtparse", 2215 | "encoding_rs", 2216 | "fancy-regex", 2217 | "filesize", 2218 | "filetime", 2219 | "getrandom 0.2.15", 2220 | "human-date-parser", 2221 | "indexmap", 2222 | "indicatif", 2223 | "itertools 0.13.0", 2224 | "log", 2225 | "lscolors", 2226 | "md-5", 2227 | "mime", 2228 | "mime_guess", 2229 | "multipart-rs", 2230 | "native-tls", 2231 | "nix", 2232 | "notify-debouncer-full", 2233 | "nu-ansi-term", 2234 | "nu-cmd-base", 2235 | "nu-color-config", 2236 | "nu-engine", 2237 | "nu-glob", 2238 | "nu-json", 2239 | "nu-parser", 2240 | "nu-path", 2241 | "nu-pretty-hex", 2242 | "nu-protocol", 2243 | "nu-system", 2244 | "nu-table", 2245 | "nu-term-grid", 2246 | "nu-utils", 2247 | "num-format", 2248 | "num-traits", 2249 | "nuon", 2250 | "oem_cp", 2251 | "open", 2252 | "os_pipe", 2253 | "pathdiff", 2254 | "percent-encoding", 2255 | "print-positions", 2256 | "procfs", 2257 | "quick-xml 0.37.2", 2258 | "rand", 2259 | "rayon", 2260 | "rmp", 2261 | "roxmltree", 2262 | "scopeguard", 2263 | "serde", 2264 | "serde_json", 2265 | "serde_urlencoded", 2266 | "serde_yaml", 2267 | "sha2", 2268 | "sysinfo", 2269 | "tabled", 2270 | "titlecase", 2271 | "toml", 2272 | "umask", 2273 | "unicode-segmentation", 2274 | "unicode-width 0.2.0", 2275 | "update-informer", 2276 | "ureq", 2277 | "url", 2278 | "uu_cp", 2279 | "uu_mkdir", 2280 | "uu_mktemp", 2281 | "uu_mv", 2282 | "uu_touch", 2283 | "uu_uname", 2284 | "uu_whoami", 2285 | "uucore", 2286 | "uuid", 2287 | "v_htmlescape", 2288 | "wax", 2289 | "web-time", 2290 | "which 7.0.1", 2291 | "windows 0.56.0", 2292 | "winreg", 2293 | ] 2294 | 2295 | [[package]] 2296 | name = "nu-derive-value" 2297 | version = "0.103.0" 2298 | source = "registry+https://github.com/rust-lang/crates.io-index" 2299 | checksum = "8f1f5198366892552a9a827a61a27e31543a0827c55ccfb6bf060489cec80d25" 2300 | dependencies = [ 2301 | "heck", 2302 | "proc-macro-error2", 2303 | "proc-macro2", 2304 | "quote", 2305 | "syn", 2306 | ] 2307 | 2308 | [[package]] 2309 | name = "nu-engine" 2310 | version = "0.103.0" 2311 | source = "registry+https://github.com/rust-lang/crates.io-index" 2312 | checksum = "0cb715bb4c18e4259d21c5b710f04f7190c9803211e2a0baa31ec3a5841daa56" 2313 | dependencies = [ 2314 | "log", 2315 | "nu-glob", 2316 | "nu-path", 2317 | "nu-protocol", 2318 | "nu-utils", 2319 | ] 2320 | 2321 | [[package]] 2322 | name = "nu-glob" 2323 | version = "0.103.0" 2324 | source = "registry+https://github.com/rust-lang/crates.io-index" 2325 | checksum = "904fa576593ed75439eec561f62824bbe55f4a05f1c8239309a939d43e0ad704" 2326 | dependencies = [ 2327 | "nu-protocol", 2328 | ] 2329 | 2330 | [[package]] 2331 | name = "nu-json" 2332 | version = "0.103.0" 2333 | source = "registry+https://github.com/rust-lang/crates.io-index" 2334 | checksum = "0da34885b46b3973e7a6d6a3e91a2014caa8cfdd7ea66d969fa1a8eec485cea9" 2335 | dependencies = [ 2336 | "linked-hash-map", 2337 | "num-traits", 2338 | "serde", 2339 | "serde_json", 2340 | ] 2341 | 2342 | [[package]] 2343 | name = "nu-parser" 2344 | version = "0.103.0" 2345 | source = "registry+https://github.com/rust-lang/crates.io-index" 2346 | checksum = "daac6d76c123d2534bcbc67ed065c4a78a54cf034e09332ed648a85339c11f91" 2347 | dependencies = [ 2348 | "bytesize", 2349 | "chrono", 2350 | "itertools 0.13.0", 2351 | "log", 2352 | "nu-engine", 2353 | "nu-path", 2354 | "nu-protocol", 2355 | "nu-utils", 2356 | "serde_json", 2357 | ] 2358 | 2359 | [[package]] 2360 | name = "nu-path" 2361 | version = "0.103.0" 2362 | source = "registry+https://github.com/rust-lang/crates.io-index" 2363 | checksum = "e6e3a55f26e42d1f98fbb4f41fa4fcc7dee1f61f13c5eabda5ca90e78825b2fa" 2364 | dependencies = [ 2365 | "dirs", 2366 | "omnipath", 2367 | "pwd", 2368 | "ref-cast", 2369 | ] 2370 | 2371 | [[package]] 2372 | name = "nu-pretty-hex" 2373 | version = "0.103.0" 2374 | source = "registry+https://github.com/rust-lang/crates.io-index" 2375 | checksum = "a10a0548f4b881bffbd4b383b531e3338868eb2ef0cd9c421eedf427a4c1e9d6" 2376 | dependencies = [ 2377 | "nu-ansi-term", 2378 | ] 2379 | 2380 | [[package]] 2381 | name = "nu-protocol" 2382 | version = "0.103.0" 2383 | source = "registry+https://github.com/rust-lang/crates.io-index" 2384 | checksum = "ca35b5860d171e8e0994d42373f62fc99fb7a0b205e5d8a38897e2869d5f6ab7" 2385 | dependencies = [ 2386 | "bytes", 2387 | "chrono", 2388 | "chrono-humanize", 2389 | "dirs", 2390 | "dirs-sys", 2391 | "fancy-regex", 2392 | "heck", 2393 | "indexmap", 2394 | "log", 2395 | "lru", 2396 | "memchr", 2397 | "miette", 2398 | "nix", 2399 | "nu-derive-value", 2400 | "nu-path", 2401 | "nu-system", 2402 | "nu-utils", 2403 | "num-format", 2404 | "os_pipe", 2405 | "serde", 2406 | "serde_json", 2407 | "strum", 2408 | "strum_macros", 2409 | "thiserror 2.0.11", 2410 | "typetag", 2411 | "web-time", 2412 | "windows-sys 0.48.0", 2413 | ] 2414 | 2415 | [[package]] 2416 | name = "nu-system" 2417 | version = "0.103.0" 2418 | source = "registry+https://github.com/rust-lang/crates.io-index" 2419 | checksum = "70bb9b1c59acd274bd36b4879e1e03491a3ee2f24689a9070c66fbd8aed23b27" 2420 | dependencies = [ 2421 | "chrono", 2422 | "itertools 0.13.0", 2423 | "libc", 2424 | "libproc", 2425 | "log", 2426 | "mach2", 2427 | "nix", 2428 | "ntapi", 2429 | "procfs", 2430 | "sysinfo", 2431 | "web-time", 2432 | "windows 0.56.0", 2433 | ] 2434 | 2435 | [[package]] 2436 | name = "nu-table" 2437 | version = "0.103.0" 2438 | source = "registry+https://github.com/rust-lang/crates.io-index" 2439 | checksum = "c9b35a78b1bcf4fb967590b78d4bef3245a071cb4f9534bba13254eb495761a3" 2440 | dependencies = [ 2441 | "fancy-regex", 2442 | "nu-ansi-term", 2443 | "nu-color-config", 2444 | "nu-engine", 2445 | "nu-protocol", 2446 | "nu-utils", 2447 | "tabled", 2448 | ] 2449 | 2450 | [[package]] 2451 | name = "nu-term-grid" 2452 | version = "0.103.0" 2453 | source = "registry+https://github.com/rust-lang/crates.io-index" 2454 | checksum = "f16be75e959343a65be5e2604902184b72448a21ce4fba22de9cc52371b76e8c" 2455 | dependencies = [ 2456 | "nu-utils", 2457 | "unicode-width 0.2.0", 2458 | ] 2459 | 2460 | [[package]] 2461 | name = "nu-utils" 2462 | version = "0.103.0" 2463 | source = "registry+https://github.com/rust-lang/crates.io-index" 2464 | checksum = "2f01345a3c94f75397020250286c536e1b306cb714b2931c1a1c9a3318254793" 2465 | dependencies = [ 2466 | "crossterm", 2467 | "crossterm_winapi", 2468 | "fancy-regex", 2469 | "log", 2470 | "lscolors", 2471 | "nix", 2472 | "num-format", 2473 | "serde", 2474 | "serde_json", 2475 | "strip-ansi-escapes", 2476 | "sys-locale", 2477 | "unicase", 2478 | ] 2479 | 2480 | [[package]] 2481 | name = "nucleo-matcher" 2482 | version = "0.3.1" 2483 | source = "registry+https://github.com/rust-lang/crates.io-index" 2484 | checksum = "bf33f538733d1a5a3494b836ba913207f14d9d4a1d3cd67030c5061bdd2cac85" 2485 | dependencies = [ 2486 | "memchr", 2487 | "unicode-segmentation", 2488 | ] 2489 | 2490 | [[package]] 2491 | name = "num-conv" 2492 | version = "0.1.0" 2493 | source = "registry+https://github.com/rust-lang/crates.io-index" 2494 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 2495 | 2496 | [[package]] 2497 | name = "num-format" 2498 | version = "0.4.4" 2499 | source = "registry+https://github.com/rust-lang/crates.io-index" 2500 | checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" 2501 | dependencies = [ 2502 | "arrayvec 0.7.6", 2503 | "itoa", 2504 | ] 2505 | 2506 | [[package]] 2507 | name = "num-traits" 2508 | version = "0.2.19" 2509 | source = "registry+https://github.com/rust-lang/crates.io-index" 2510 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 2511 | dependencies = [ 2512 | "autocfg", 2513 | ] 2514 | 2515 | [[package]] 2516 | name = "num_threads" 2517 | version = "0.1.7" 2518 | source = "registry+https://github.com/rust-lang/crates.io-index" 2519 | checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" 2520 | dependencies = [ 2521 | "libc", 2522 | ] 2523 | 2524 | [[package]] 2525 | name = "number_prefix" 2526 | version = "0.4.0" 2527 | source = "registry+https://github.com/rust-lang/crates.io-index" 2528 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 2529 | 2530 | [[package]] 2531 | name = "nuon" 2532 | version = "0.103.0" 2533 | source = "registry+https://github.com/rust-lang/crates.io-index" 2534 | checksum = "19acc9cc8769e6428c244229bcd042c222088cca8c6ebb045df630e79922cd16" 2535 | dependencies = [ 2536 | "nu-engine", 2537 | "nu-parser", 2538 | "nu-protocol", 2539 | "nu-utils", 2540 | ] 2541 | 2542 | [[package]] 2543 | name = "object" 2544 | version = "0.36.7" 2545 | source = "registry+https://github.com/rust-lang/crates.io-index" 2546 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 2547 | dependencies = [ 2548 | "memchr", 2549 | ] 2550 | 2551 | [[package]] 2552 | name = "oem_cp" 2553 | version = "2.0.0" 2554 | source = "registry+https://github.com/rust-lang/crates.io-index" 2555 | checksum = "330138902ab4dab09a86e6b7ab7ddeffb5f8435d52fe0df1bce8b06a17b10ee4" 2556 | dependencies = [ 2557 | "phf", 2558 | "phf_codegen", 2559 | "serde", 2560 | "serde_json", 2561 | ] 2562 | 2563 | [[package]] 2564 | name = "omnipath" 2565 | version = "0.1.6" 2566 | source = "registry+https://github.com/rust-lang/crates.io-index" 2567 | checksum = "80adb31078122c880307e9cdfd4e3361e6545c319f9b9dcafcb03acd3b51a575" 2568 | 2569 | [[package]] 2570 | name = "once_cell" 2571 | version = "1.20.2" 2572 | source = "registry+https://github.com/rust-lang/crates.io-index" 2573 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 2574 | 2575 | [[package]] 2576 | name = "open" 2577 | version = "5.3.2" 2578 | source = "registry+https://github.com/rust-lang/crates.io-index" 2579 | checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" 2580 | dependencies = [ 2581 | "is-wsl", 2582 | "libc", 2583 | "pathdiff", 2584 | ] 2585 | 2586 | [[package]] 2587 | name = "openssl" 2588 | version = "0.10.69" 2589 | source = "registry+https://github.com/rust-lang/crates.io-index" 2590 | checksum = "f5e534d133a060a3c19daec1eb3e98ec6f4685978834f2dbadfe2ec215bab64e" 2591 | dependencies = [ 2592 | "bitflags 2.8.0", 2593 | "cfg-if", 2594 | "foreign-types", 2595 | "libc", 2596 | "once_cell", 2597 | "openssl-macros", 2598 | "openssl-sys", 2599 | ] 2600 | 2601 | [[package]] 2602 | name = "openssl-macros" 2603 | version = "0.1.1" 2604 | source = "registry+https://github.com/rust-lang/crates.io-index" 2605 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 2606 | dependencies = [ 2607 | "proc-macro2", 2608 | "quote", 2609 | "syn", 2610 | ] 2611 | 2612 | [[package]] 2613 | name = "openssl-probe" 2614 | version = "0.1.6" 2615 | source = "registry+https://github.com/rust-lang/crates.io-index" 2616 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 2617 | 2618 | [[package]] 2619 | name = "openssl-sys" 2620 | version = "0.9.104" 2621 | source = "registry+https://github.com/rust-lang/crates.io-index" 2622 | checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" 2623 | dependencies = [ 2624 | "cc", 2625 | "libc", 2626 | "pkg-config", 2627 | "vcpkg", 2628 | ] 2629 | 2630 | [[package]] 2631 | name = "option-ext" 2632 | version = "0.2.0" 2633 | source = "registry+https://github.com/rust-lang/crates.io-index" 2634 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 2635 | 2636 | [[package]] 2637 | name = "os_display" 2638 | version = "0.1.3" 2639 | source = "registry+https://github.com/rust-lang/crates.io-index" 2640 | checksum = "7a6229bad892b46b0dcfaaeb18ad0d2e56400f5aaea05b768bde96e73676cf75" 2641 | dependencies = [ 2642 | "unicode-width 0.1.11", 2643 | ] 2644 | 2645 | [[package]] 2646 | name = "os_pipe" 2647 | version = "1.2.1" 2648 | source = "registry+https://github.com/rust-lang/crates.io-index" 2649 | checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" 2650 | dependencies = [ 2651 | "libc", 2652 | "windows-sys 0.59.0", 2653 | ] 2654 | 2655 | [[package]] 2656 | name = "owo-colors" 2657 | version = "4.1.0" 2658 | source = "registry+https://github.com/rust-lang/crates.io-index" 2659 | checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" 2660 | 2661 | [[package]] 2662 | name = "papergrid" 2663 | version = "0.13.0" 2664 | source = "registry+https://github.com/rust-lang/crates.io-index" 2665 | checksum = "d2b0f8def1f117e13c895f3eda65a7b5650688da29d6ad04635f61bc7b92eebd" 2666 | dependencies = [ 2667 | "ansi-str", 2668 | "ansitok", 2669 | "bytecount", 2670 | "fnv", 2671 | "unicode-width 0.2.0", 2672 | ] 2673 | 2674 | [[package]] 2675 | name = "parking_lot" 2676 | version = "0.12.3" 2677 | source = "registry+https://github.com/rust-lang/crates.io-index" 2678 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 2679 | dependencies = [ 2680 | "lock_api", 2681 | "parking_lot_core", 2682 | ] 2683 | 2684 | [[package]] 2685 | name = "parking_lot_core" 2686 | version = "0.9.10" 2687 | source = "registry+https://github.com/rust-lang/crates.io-index" 2688 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 2689 | dependencies = [ 2690 | "cfg-if", 2691 | "libc", 2692 | "redox_syscall", 2693 | "smallvec", 2694 | "windows-targets 0.52.6", 2695 | ] 2696 | 2697 | [[package]] 2698 | name = "parse-zoneinfo" 2699 | version = "0.3.1" 2700 | source = "registry+https://github.com/rust-lang/crates.io-index" 2701 | checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" 2702 | dependencies = [ 2703 | "regex", 2704 | ] 2705 | 2706 | [[package]] 2707 | name = "parse_datetime" 2708 | version = "0.6.0" 2709 | source = "registry+https://github.com/rust-lang/crates.io-index" 2710 | checksum = "a8720474e3dd4af20cea8716703498b9f3b690f318fa9d9d9e2e38eaf44b96d0" 2711 | dependencies = [ 2712 | "chrono", 2713 | "nom", 2714 | "regex", 2715 | ] 2716 | 2717 | [[package]] 2718 | name = "paste" 2719 | version = "1.0.15" 2720 | source = "registry+https://github.com/rust-lang/crates.io-index" 2721 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 2722 | 2723 | [[package]] 2724 | name = "pathdiff" 2725 | version = "0.2.3" 2726 | source = "registry+https://github.com/rust-lang/crates.io-index" 2727 | checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" 2728 | 2729 | [[package]] 2730 | name = "percent-encoding" 2731 | version = "2.3.1" 2732 | source = "registry+https://github.com/rust-lang/crates.io-index" 2733 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 2734 | 2735 | [[package]] 2736 | name = "pest" 2737 | version = "2.7.15" 2738 | source = "registry+https://github.com/rust-lang/crates.io-index" 2739 | checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" 2740 | dependencies = [ 2741 | "memchr", 2742 | "thiserror 2.0.11", 2743 | "ucd-trie", 2744 | ] 2745 | 2746 | [[package]] 2747 | name = "pest_derive" 2748 | version = "2.7.15" 2749 | source = "registry+https://github.com/rust-lang/crates.io-index" 2750 | checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" 2751 | dependencies = [ 2752 | "pest", 2753 | "pest_generator", 2754 | ] 2755 | 2756 | [[package]] 2757 | name = "pest_generator" 2758 | version = "2.7.15" 2759 | source = "registry+https://github.com/rust-lang/crates.io-index" 2760 | checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" 2761 | dependencies = [ 2762 | "pest", 2763 | "pest_meta", 2764 | "proc-macro2", 2765 | "quote", 2766 | "syn", 2767 | ] 2768 | 2769 | [[package]] 2770 | name = "pest_meta" 2771 | version = "2.7.15" 2772 | source = "registry+https://github.com/rust-lang/crates.io-index" 2773 | checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" 2774 | dependencies = [ 2775 | "once_cell", 2776 | "pest", 2777 | "sha2", 2778 | ] 2779 | 2780 | [[package]] 2781 | name = "phf" 2782 | version = "0.11.3" 2783 | source = "registry+https://github.com/rust-lang/crates.io-index" 2784 | checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" 2785 | dependencies = [ 2786 | "phf_shared", 2787 | ] 2788 | 2789 | [[package]] 2790 | name = "phf_codegen" 2791 | version = "0.11.3" 2792 | source = "registry+https://github.com/rust-lang/crates.io-index" 2793 | checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" 2794 | dependencies = [ 2795 | "phf_generator", 2796 | "phf_shared", 2797 | ] 2798 | 2799 | [[package]] 2800 | name = "phf_generator" 2801 | version = "0.11.3" 2802 | source = "registry+https://github.com/rust-lang/crates.io-index" 2803 | checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" 2804 | dependencies = [ 2805 | "phf_shared", 2806 | "rand", 2807 | ] 2808 | 2809 | [[package]] 2810 | name = "phf_shared" 2811 | version = "0.11.3" 2812 | source = "registry+https://github.com/rust-lang/crates.io-index" 2813 | checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" 2814 | dependencies = [ 2815 | "siphasher", 2816 | ] 2817 | 2818 | [[package]] 2819 | name = "pin-project-lite" 2820 | version = "0.2.16" 2821 | source = "registry+https://github.com/rust-lang/crates.io-index" 2822 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 2823 | 2824 | [[package]] 2825 | name = "pin-utils" 2826 | version = "0.1.0" 2827 | source = "registry+https://github.com/rust-lang/crates.io-index" 2828 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 2829 | 2830 | [[package]] 2831 | name = "pkg-config" 2832 | version = "0.3.31" 2833 | source = "registry+https://github.com/rust-lang/crates.io-index" 2834 | checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 2835 | 2836 | [[package]] 2837 | name = "platform-info" 2838 | version = "2.0.5" 2839 | source = "registry+https://github.com/rust-lang/crates.io-index" 2840 | checksum = "7539aeb3fdd8cb4f6a331307cf71a1039cee75e94e8a71725b9484f4a0d9451a" 2841 | dependencies = [ 2842 | "libc", 2843 | "winapi", 2844 | ] 2845 | 2846 | [[package]] 2847 | name = "pori" 2848 | version = "0.0.0" 2849 | source = "registry+https://github.com/rust-lang/crates.io-index" 2850 | checksum = "a4a63d338dec139f56dacc692ca63ad35a6be6a797442479b55acd611d79e906" 2851 | dependencies = [ 2852 | "nom", 2853 | ] 2854 | 2855 | [[package]] 2856 | name = "portable-atomic" 2857 | version = "1.10.0" 2858 | source = "registry+https://github.com/rust-lang/crates.io-index" 2859 | checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" 2860 | 2861 | [[package]] 2862 | name = "powerfmt" 2863 | version = "0.2.0" 2864 | source = "registry+https://github.com/rust-lang/crates.io-index" 2865 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 2866 | 2867 | [[package]] 2868 | name = "ppv-lite86" 2869 | version = "0.2.20" 2870 | source = "registry+https://github.com/rust-lang/crates.io-index" 2871 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 2872 | dependencies = [ 2873 | "zerocopy", 2874 | ] 2875 | 2876 | [[package]] 2877 | name = "prettyplease" 2878 | version = "0.2.29" 2879 | source = "registry+https://github.com/rust-lang/crates.io-index" 2880 | checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" 2881 | dependencies = [ 2882 | "proc-macro2", 2883 | "syn", 2884 | ] 2885 | 2886 | [[package]] 2887 | name = "print-positions" 2888 | version = "0.6.1" 2889 | source = "registry+https://github.com/rust-lang/crates.io-index" 2890 | checksum = "1df593470e3ef502e48cb0cfc9a3a61e5f61e967b78e1ed35a67ac615cfbd208" 2891 | dependencies = [ 2892 | "unicode-segmentation", 2893 | ] 2894 | 2895 | [[package]] 2896 | name = "proc-macro-error-attr2" 2897 | version = "2.0.0" 2898 | source = "registry+https://github.com/rust-lang/crates.io-index" 2899 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 2900 | dependencies = [ 2901 | "proc-macro2", 2902 | "quote", 2903 | ] 2904 | 2905 | [[package]] 2906 | name = "proc-macro-error2" 2907 | version = "2.0.1" 2908 | source = "registry+https://github.com/rust-lang/crates.io-index" 2909 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 2910 | dependencies = [ 2911 | "proc-macro-error-attr2", 2912 | "proc-macro2", 2913 | "quote", 2914 | "syn", 2915 | ] 2916 | 2917 | [[package]] 2918 | name = "proc-macro2" 2919 | version = "1.0.93" 2920 | source = "registry+https://github.com/rust-lang/crates.io-index" 2921 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 2922 | dependencies = [ 2923 | "unicode-ident", 2924 | ] 2925 | 2926 | [[package]] 2927 | name = "procfs" 2928 | version = "0.17.0" 2929 | source = "registry+https://github.com/rust-lang/crates.io-index" 2930 | checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f" 2931 | dependencies = [ 2932 | "bitflags 2.8.0", 2933 | "chrono", 2934 | "flate2", 2935 | "hex", 2936 | "procfs-core", 2937 | "rustix", 2938 | ] 2939 | 2940 | [[package]] 2941 | name = "procfs-core" 2942 | version = "0.17.0" 2943 | source = "registry+https://github.com/rust-lang/crates.io-index" 2944 | checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" 2945 | dependencies = [ 2946 | "bitflags 2.8.0", 2947 | "chrono", 2948 | "hex", 2949 | ] 2950 | 2951 | [[package]] 2952 | name = "pure-rust-locales" 2953 | version = "0.8.1" 2954 | source = "registry+https://github.com/rust-lang/crates.io-index" 2955 | checksum = "1190fd18ae6ce9e137184f207593877e70f39b015040156b1e05081cdfe3733a" 2956 | 2957 | [[package]] 2958 | name = "pwd" 2959 | version = "1.4.0" 2960 | source = "registry+https://github.com/rust-lang/crates.io-index" 2961 | checksum = "72c71c0c79b9701efe4e1e4b563b2016dd4ee789eb99badcb09d61ac4b92e4a2" 2962 | dependencies = [ 2963 | "libc", 2964 | "thiserror 1.0.69", 2965 | ] 2966 | 2967 | [[package]] 2968 | name = "quick-error" 2969 | version = "2.0.1" 2970 | source = "registry+https://github.com/rust-lang/crates.io-index" 2971 | checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" 2972 | 2973 | [[package]] 2974 | name = "quick-xml" 2975 | version = "0.31.0" 2976 | source = "registry+https://github.com/rust-lang/crates.io-index" 2977 | checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" 2978 | dependencies = [ 2979 | "encoding_rs", 2980 | "memchr", 2981 | ] 2982 | 2983 | [[package]] 2984 | name = "quick-xml" 2985 | version = "0.37.2" 2986 | source = "registry+https://github.com/rust-lang/crates.io-index" 2987 | checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003" 2988 | dependencies = [ 2989 | "memchr", 2990 | ] 2991 | 2992 | [[package]] 2993 | name = "quote" 2994 | version = "1.0.38" 2995 | source = "registry+https://github.com/rust-lang/crates.io-index" 2996 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 2997 | dependencies = [ 2998 | "proc-macro2", 2999 | ] 3000 | 3001 | [[package]] 3002 | name = "rand" 3003 | version = "0.8.5" 3004 | source = "registry+https://github.com/rust-lang/crates.io-index" 3005 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 3006 | dependencies = [ 3007 | "libc", 3008 | "rand_chacha", 3009 | "rand_core", 3010 | ] 3011 | 3012 | [[package]] 3013 | name = "rand_chacha" 3014 | version = "0.3.1" 3015 | source = "registry+https://github.com/rust-lang/crates.io-index" 3016 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 3017 | dependencies = [ 3018 | "ppv-lite86", 3019 | "rand_core", 3020 | ] 3021 | 3022 | [[package]] 3023 | name = "rand_core" 3024 | version = "0.6.4" 3025 | source = "registry+https://github.com/rust-lang/crates.io-index" 3026 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 3027 | dependencies = [ 3028 | "getrandom 0.2.15", 3029 | ] 3030 | 3031 | [[package]] 3032 | name = "rayon" 3033 | version = "1.10.0" 3034 | source = "registry+https://github.com/rust-lang/crates.io-index" 3035 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 3036 | dependencies = [ 3037 | "either", 3038 | "rayon-core", 3039 | ] 3040 | 3041 | [[package]] 3042 | name = "rayon-core" 3043 | version = "1.12.1" 3044 | source = "registry+https://github.com/rust-lang/crates.io-index" 3045 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 3046 | dependencies = [ 3047 | "crossbeam-deque", 3048 | "crossbeam-utils", 3049 | ] 3050 | 3051 | [[package]] 3052 | name = "redox_syscall" 3053 | version = "0.5.8" 3054 | source = "registry+https://github.com/rust-lang/crates.io-index" 3055 | checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" 3056 | dependencies = [ 3057 | "bitflags 2.8.0", 3058 | ] 3059 | 3060 | [[package]] 3061 | name = "redox_users" 3062 | version = "0.4.6" 3063 | source = "registry+https://github.com/rust-lang/crates.io-index" 3064 | checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" 3065 | dependencies = [ 3066 | "getrandom 0.2.15", 3067 | "libredox", 3068 | "thiserror 1.0.69", 3069 | ] 3070 | 3071 | [[package]] 3072 | name = "reedline" 3073 | version = "0.39.0" 3074 | source = "registry+https://github.com/rust-lang/crates.io-index" 3075 | checksum = "dd4728ee71d2aa3a364ee64470d1aa64b3f0467b2d28b73df15259d005dec64a" 3076 | dependencies = [ 3077 | "chrono", 3078 | "crossterm", 3079 | "fd-lock", 3080 | "itertools 0.13.0", 3081 | "nu-ansi-term", 3082 | "rusqlite", 3083 | "serde", 3084 | "serde_json", 3085 | "strip-ansi-escapes", 3086 | "strum", 3087 | "strum_macros", 3088 | "thiserror 1.0.69", 3089 | "unicode-segmentation", 3090 | "unicode-width 0.1.11", 3091 | ] 3092 | 3093 | [[package]] 3094 | name = "ref-cast" 3095 | version = "1.0.24" 3096 | source = "registry+https://github.com/rust-lang/crates.io-index" 3097 | checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" 3098 | dependencies = [ 3099 | "ref-cast-impl", 3100 | ] 3101 | 3102 | [[package]] 3103 | name = "ref-cast-impl" 3104 | version = "1.0.24" 3105 | source = "registry+https://github.com/rust-lang/crates.io-index" 3106 | checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" 3107 | dependencies = [ 3108 | "proc-macro2", 3109 | "quote", 3110 | "syn", 3111 | ] 3112 | 3113 | [[package]] 3114 | name = "regex" 3115 | version = "1.11.1" 3116 | source = "registry+https://github.com/rust-lang/crates.io-index" 3117 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 3118 | dependencies = [ 3119 | "aho-corasick", 3120 | "memchr", 3121 | "regex-automata", 3122 | "regex-syntax", 3123 | ] 3124 | 3125 | [[package]] 3126 | name = "regex-automata" 3127 | version = "0.4.9" 3128 | source = "registry+https://github.com/rust-lang/crates.io-index" 3129 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 3130 | dependencies = [ 3131 | "aho-corasick", 3132 | "memchr", 3133 | "regex-syntax", 3134 | ] 3135 | 3136 | [[package]] 3137 | name = "regex-syntax" 3138 | version = "0.8.5" 3139 | source = "registry+https://github.com/rust-lang/crates.io-index" 3140 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 3141 | 3142 | [[package]] 3143 | name = "reqwest" 3144 | version = "0.12.15" 3145 | source = "registry+https://github.com/rust-lang/crates.io-index" 3146 | checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" 3147 | dependencies = [ 3148 | "base64", 3149 | "bytes", 3150 | "futures-channel", 3151 | "futures-core", 3152 | "futures-util", 3153 | "http", 3154 | "http-body", 3155 | "http-body-util", 3156 | "hyper", 3157 | "hyper-tls", 3158 | "hyper-util", 3159 | "ipnet", 3160 | "js-sys", 3161 | "log", 3162 | "mime", 3163 | "native-tls", 3164 | "once_cell", 3165 | "percent-encoding", 3166 | "pin-project-lite", 3167 | "rustls-pemfile", 3168 | "serde", 3169 | "serde_json", 3170 | "serde_urlencoded", 3171 | "sync_wrapper", 3172 | "tokio", 3173 | "tokio-native-tls", 3174 | "tower", 3175 | "tower-service", 3176 | "url", 3177 | "wasm-bindgen", 3178 | "wasm-bindgen-futures", 3179 | "web-sys", 3180 | "windows-registry", 3181 | ] 3182 | 3183 | [[package]] 3184 | name = "ring" 3185 | version = "0.17.8" 3186 | source = "registry+https://github.com/rust-lang/crates.io-index" 3187 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 3188 | dependencies = [ 3189 | "cc", 3190 | "cfg-if", 3191 | "getrandom 0.2.15", 3192 | "libc", 3193 | "spin", 3194 | "untrusted", 3195 | "windows-sys 0.52.0", 3196 | ] 3197 | 3198 | [[package]] 3199 | name = "rmp" 3200 | version = "0.8.14" 3201 | source = "registry+https://github.com/rust-lang/crates.io-index" 3202 | checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" 3203 | dependencies = [ 3204 | "byteorder", 3205 | "num-traits", 3206 | "paste", 3207 | ] 3208 | 3209 | [[package]] 3210 | name = "roxmltree" 3211 | version = "0.20.0" 3212 | source = "registry+https://github.com/rust-lang/crates.io-index" 3213 | checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" 3214 | 3215 | [[package]] 3216 | name = "rusqlite" 3217 | version = "0.31.0" 3218 | source = "registry+https://github.com/rust-lang/crates.io-index" 3219 | checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" 3220 | dependencies = [ 3221 | "bitflags 2.8.0", 3222 | "fallible-iterator", 3223 | "fallible-streaming-iterator", 3224 | "hashlink", 3225 | "libsqlite3-sys", 3226 | "smallvec", 3227 | ] 3228 | 3229 | [[package]] 3230 | name = "rust-embed" 3231 | version = "8.6.0" 3232 | source = "registry+https://github.com/rust-lang/crates.io-index" 3233 | checksum = "0b3aba5104622db5c9fc61098de54708feb732e7763d7faa2fa625899f00bf6f" 3234 | dependencies = [ 3235 | "rust-embed-impl", 3236 | "rust-embed-utils", 3237 | "walkdir", 3238 | ] 3239 | 3240 | [[package]] 3241 | name = "rust-embed-impl" 3242 | version = "8.6.0" 3243 | source = "registry+https://github.com/rust-lang/crates.io-index" 3244 | checksum = "1f198c73be048d2c5aa8e12f7960ad08443e56fd39cc26336719fdb4ea0ebaae" 3245 | dependencies = [ 3246 | "proc-macro2", 3247 | "quote", 3248 | "rust-embed-utils", 3249 | "syn", 3250 | "walkdir", 3251 | ] 3252 | 3253 | [[package]] 3254 | name = "rust-embed-utils" 3255 | version = "8.6.0" 3256 | source = "registry+https://github.com/rust-lang/crates.io-index" 3257 | checksum = "5a2fcdc9f40c8dc2922842ca9add611ad19f332227fc651d015881ad1552bd9a" 3258 | dependencies = [ 3259 | "sha2", 3260 | "walkdir", 3261 | ] 3262 | 3263 | [[package]] 3264 | name = "rust_decimal" 3265 | version = "1.36.0" 3266 | source = "registry+https://github.com/rust-lang/crates.io-index" 3267 | checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" 3268 | dependencies = [ 3269 | "arrayvec 0.7.6", 3270 | "num-traits", 3271 | ] 3272 | 3273 | [[package]] 3274 | name = "rustc-demangle" 3275 | version = "0.1.24" 3276 | source = "registry+https://github.com/rust-lang/crates.io-index" 3277 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 3278 | 3279 | [[package]] 3280 | name = "rustc-hash" 3281 | version = "1.1.0" 3282 | source = "registry+https://github.com/rust-lang/crates.io-index" 3283 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 3284 | 3285 | [[package]] 3286 | name = "rustix" 3287 | version = "0.38.44" 3288 | source = "registry+https://github.com/rust-lang/crates.io-index" 3289 | checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" 3290 | dependencies = [ 3291 | "bitflags 2.8.0", 3292 | "errno", 3293 | "libc", 3294 | "linux-raw-sys", 3295 | "windows-sys 0.59.0", 3296 | ] 3297 | 3298 | [[package]] 3299 | name = "rustls" 3300 | version = "0.23.23" 3301 | source = "registry+https://github.com/rust-lang/crates.io-index" 3302 | checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" 3303 | dependencies = [ 3304 | "aws-lc-rs", 3305 | "log", 3306 | "once_cell", 3307 | "rustls-pki-types", 3308 | "rustls-webpki", 3309 | "subtle", 3310 | "zeroize", 3311 | ] 3312 | 3313 | [[package]] 3314 | name = "rustls-pemfile" 3315 | version = "2.2.0" 3316 | source = "registry+https://github.com/rust-lang/crates.io-index" 3317 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 3318 | dependencies = [ 3319 | "rustls-pki-types", 3320 | ] 3321 | 3322 | [[package]] 3323 | name = "rustls-pki-types" 3324 | version = "1.11.0" 3325 | source = "registry+https://github.com/rust-lang/crates.io-index" 3326 | checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" 3327 | 3328 | [[package]] 3329 | name = "rustls-webpki" 3330 | version = "0.102.8" 3331 | source = "registry+https://github.com/rust-lang/crates.io-index" 3332 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 3333 | dependencies = [ 3334 | "aws-lc-rs", 3335 | "ring", 3336 | "rustls-pki-types", 3337 | "untrusted", 3338 | ] 3339 | 3340 | [[package]] 3341 | name = "rustversion" 3342 | version = "1.0.19" 3343 | source = "registry+https://github.com/rust-lang/crates.io-index" 3344 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 3345 | 3346 | [[package]] 3347 | name = "ryu" 3348 | version = "1.0.18" 3349 | source = "registry+https://github.com/rust-lang/crates.io-index" 3350 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 3351 | 3352 | [[package]] 3353 | name = "same-file" 3354 | version = "1.0.6" 3355 | source = "registry+https://github.com/rust-lang/crates.io-index" 3356 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 3357 | dependencies = [ 3358 | "winapi-util", 3359 | ] 3360 | 3361 | [[package]] 3362 | name = "schannel" 3363 | version = "0.1.27" 3364 | source = "registry+https://github.com/rust-lang/crates.io-index" 3365 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 3366 | dependencies = [ 3367 | "windows-sys 0.59.0", 3368 | ] 3369 | 3370 | [[package]] 3371 | name = "scopeguard" 3372 | version = "1.2.0" 3373 | source = "registry+https://github.com/rust-lang/crates.io-index" 3374 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 3375 | 3376 | [[package]] 3377 | name = "scru128" 3378 | version = "3.1.0" 3379 | source = "registry+https://github.com/rust-lang/crates.io-index" 3380 | checksum = "a8db8ec4ae75494860073f4ea781388356167027e42757bb193e31145dae5e1f" 3381 | dependencies = [ 3382 | "fstr", 3383 | "rand", 3384 | "rand_chacha", 3385 | "serde", 3386 | ] 3387 | 3388 | [[package]] 3389 | name = "security-framework" 3390 | version = "2.11.1" 3391 | source = "registry+https://github.com/rust-lang/crates.io-index" 3392 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 3393 | dependencies = [ 3394 | "bitflags 2.8.0", 3395 | "core-foundation", 3396 | "core-foundation-sys", 3397 | "libc", 3398 | "security-framework-sys", 3399 | ] 3400 | 3401 | [[package]] 3402 | name = "security-framework-sys" 3403 | version = "2.14.0" 3404 | source = "registry+https://github.com/rust-lang/crates.io-index" 3405 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 3406 | dependencies = [ 3407 | "core-foundation-sys", 3408 | "libc", 3409 | ] 3410 | 3411 | [[package]] 3412 | name = "semver" 3413 | version = "1.0.26" 3414 | source = "registry+https://github.com/rust-lang/crates.io-index" 3415 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 3416 | 3417 | [[package]] 3418 | name = "serde" 3419 | version = "1.0.217" 3420 | source = "registry+https://github.com/rust-lang/crates.io-index" 3421 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 3422 | dependencies = [ 3423 | "serde_derive", 3424 | ] 3425 | 3426 | [[package]] 3427 | name = "serde_derive" 3428 | version = "1.0.217" 3429 | source = "registry+https://github.com/rust-lang/crates.io-index" 3430 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 3431 | dependencies = [ 3432 | "proc-macro2", 3433 | "quote", 3434 | "syn", 3435 | ] 3436 | 3437 | [[package]] 3438 | name = "serde_json" 3439 | version = "1.0.137" 3440 | source = "registry+https://github.com/rust-lang/crates.io-index" 3441 | checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" 3442 | dependencies = [ 3443 | "indexmap", 3444 | "itoa", 3445 | "memchr", 3446 | "ryu", 3447 | "serde", 3448 | ] 3449 | 3450 | [[package]] 3451 | name = "serde_spanned" 3452 | version = "0.6.8" 3453 | source = "registry+https://github.com/rust-lang/crates.io-index" 3454 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 3455 | dependencies = [ 3456 | "serde", 3457 | ] 3458 | 3459 | [[package]] 3460 | name = "serde_urlencoded" 3461 | version = "0.7.1" 3462 | source = "registry+https://github.com/rust-lang/crates.io-index" 3463 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 3464 | dependencies = [ 3465 | "form_urlencoded", 3466 | "itoa", 3467 | "ryu", 3468 | "serde", 3469 | ] 3470 | 3471 | [[package]] 3472 | name = "serde_yaml" 3473 | version = "0.9.34+deprecated" 3474 | source = "registry+https://github.com/rust-lang/crates.io-index" 3475 | checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" 3476 | dependencies = [ 3477 | "indexmap", 3478 | "itoa", 3479 | "ryu", 3480 | "serde", 3481 | "unsafe-libyaml", 3482 | ] 3483 | 3484 | [[package]] 3485 | name = "sha1_smol" 3486 | version = "1.0.1" 3487 | source = "registry+https://github.com/rust-lang/crates.io-index" 3488 | checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" 3489 | 3490 | [[package]] 3491 | name = "sha2" 3492 | version = "0.10.8" 3493 | source = "registry+https://github.com/rust-lang/crates.io-index" 3494 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 3495 | dependencies = [ 3496 | "cfg-if", 3497 | "cpufeatures", 3498 | "digest", 3499 | ] 3500 | 3501 | [[package]] 3502 | name = "shadow-rs" 3503 | version = "0.38.1" 3504 | source = "registry+https://github.com/rust-lang/crates.io-index" 3505 | checksum = "6ec14cc798c29f4bf74a6c4299c657c04d4e9fba03875c1f0eec569af03aed89" 3506 | dependencies = [ 3507 | "const_format", 3508 | "is_debug", 3509 | "time", 3510 | ] 3511 | 3512 | [[package]] 3513 | name = "shell-words" 3514 | version = "1.1.0" 3515 | source = "registry+https://github.com/rust-lang/crates.io-index" 3516 | checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" 3517 | 3518 | [[package]] 3519 | name = "shlex" 3520 | version = "1.3.0" 3521 | source = "registry+https://github.com/rust-lang/crates.io-index" 3522 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 3523 | 3524 | [[package]] 3525 | name = "signal-hook" 3526 | version = "0.3.17" 3527 | source = "registry+https://github.com/rust-lang/crates.io-index" 3528 | checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" 3529 | dependencies = [ 3530 | "libc", 3531 | "signal-hook-registry", 3532 | ] 3533 | 3534 | [[package]] 3535 | name = "signal-hook-mio" 3536 | version = "0.2.4" 3537 | source = "registry+https://github.com/rust-lang/crates.io-index" 3538 | checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" 3539 | dependencies = [ 3540 | "libc", 3541 | "mio 1.0.3", 3542 | "signal-hook", 3543 | ] 3544 | 3545 | [[package]] 3546 | name = "signal-hook-registry" 3547 | version = "1.4.2" 3548 | source = "registry+https://github.com/rust-lang/crates.io-index" 3549 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 3550 | dependencies = [ 3551 | "libc", 3552 | ] 3553 | 3554 | [[package]] 3555 | name = "simd-adler32" 3556 | version = "0.3.7" 3557 | source = "registry+https://github.com/rust-lang/crates.io-index" 3558 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 3559 | 3560 | [[package]] 3561 | name = "siphasher" 3562 | version = "1.0.1" 3563 | source = "registry+https://github.com/rust-lang/crates.io-index" 3564 | checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" 3565 | 3566 | [[package]] 3567 | name = "slab" 3568 | version = "0.4.9" 3569 | source = "registry+https://github.com/rust-lang/crates.io-index" 3570 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 3571 | dependencies = [ 3572 | "autocfg", 3573 | ] 3574 | 3575 | [[package]] 3576 | name = "smallvec" 3577 | version = "1.13.2" 3578 | source = "registry+https://github.com/rust-lang/crates.io-index" 3579 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 3580 | 3581 | [[package]] 3582 | name = "socket2" 3583 | version = "0.5.8" 3584 | source = "registry+https://github.com/rust-lang/crates.io-index" 3585 | checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" 3586 | dependencies = [ 3587 | "libc", 3588 | "windows-sys 0.52.0", 3589 | ] 3590 | 3591 | [[package]] 3592 | name = "spin" 3593 | version = "0.9.8" 3594 | source = "registry+https://github.com/rust-lang/crates.io-index" 3595 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 3596 | 3597 | [[package]] 3598 | name = "stable_deref_trait" 3599 | version = "1.2.0" 3600 | source = "registry+https://github.com/rust-lang/crates.io-index" 3601 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 3602 | 3603 | [[package]] 3604 | name = "strip-ansi-escapes" 3605 | version = "0.2.1" 3606 | source = "registry+https://github.com/rust-lang/crates.io-index" 3607 | checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" 3608 | dependencies = [ 3609 | "vte 0.14.1", 3610 | ] 3611 | 3612 | [[package]] 3613 | name = "strsim" 3614 | version = "0.11.1" 3615 | source = "registry+https://github.com/rust-lang/crates.io-index" 3616 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 3617 | 3618 | [[package]] 3619 | name = "strum" 3620 | version = "0.26.3" 3621 | source = "registry+https://github.com/rust-lang/crates.io-index" 3622 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 3623 | 3624 | [[package]] 3625 | name = "strum_macros" 3626 | version = "0.26.4" 3627 | source = "registry+https://github.com/rust-lang/crates.io-index" 3628 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 3629 | dependencies = [ 3630 | "heck", 3631 | "proc-macro2", 3632 | "quote", 3633 | "rustversion", 3634 | "syn", 3635 | ] 3636 | 3637 | [[package]] 3638 | name = "subtle" 3639 | version = "2.6.1" 3640 | source = "registry+https://github.com/rust-lang/crates.io-index" 3641 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 3642 | 3643 | [[package]] 3644 | name = "supports-color" 3645 | version = "3.0.2" 3646 | source = "registry+https://github.com/rust-lang/crates.io-index" 3647 | checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" 3648 | dependencies = [ 3649 | "is_ci", 3650 | ] 3651 | 3652 | [[package]] 3653 | name = "supports-hyperlinks" 3654 | version = "3.1.0" 3655 | source = "registry+https://github.com/rust-lang/crates.io-index" 3656 | checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" 3657 | 3658 | [[package]] 3659 | name = "supports-unicode" 3660 | version = "3.0.0" 3661 | source = "registry+https://github.com/rust-lang/crates.io-index" 3662 | checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" 3663 | 3664 | [[package]] 3665 | name = "syn" 3666 | version = "2.0.96" 3667 | source = "registry+https://github.com/rust-lang/crates.io-index" 3668 | checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" 3669 | dependencies = [ 3670 | "proc-macro2", 3671 | "quote", 3672 | "unicode-ident", 3673 | ] 3674 | 3675 | [[package]] 3676 | name = "sync_wrapper" 3677 | version = "1.0.2" 3678 | source = "registry+https://github.com/rust-lang/crates.io-index" 3679 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 3680 | dependencies = [ 3681 | "futures-core", 3682 | ] 3683 | 3684 | [[package]] 3685 | name = "synstructure" 3686 | version = "0.13.1" 3687 | source = "registry+https://github.com/rust-lang/crates.io-index" 3688 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 3689 | dependencies = [ 3690 | "proc-macro2", 3691 | "quote", 3692 | "syn", 3693 | ] 3694 | 3695 | [[package]] 3696 | name = "sys-locale" 3697 | version = "0.3.2" 3698 | source = "registry+https://github.com/rust-lang/crates.io-index" 3699 | checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" 3700 | dependencies = [ 3701 | "libc", 3702 | ] 3703 | 3704 | [[package]] 3705 | name = "sysinfo" 3706 | version = "0.33.1" 3707 | source = "registry+https://github.com/rust-lang/crates.io-index" 3708 | checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" 3709 | dependencies = [ 3710 | "core-foundation-sys", 3711 | "libc", 3712 | "memchr", 3713 | "ntapi", 3714 | "rayon", 3715 | "windows 0.57.0", 3716 | ] 3717 | 3718 | [[package]] 3719 | name = "tabled" 3720 | version = "0.17.0" 3721 | source = "registry+https://github.com/rust-lang/crates.io-index" 3722 | checksum = "c6709222f3973137427ce50559cd564dc187a95b9cfe01613d2f4e93610e510a" 3723 | dependencies = [ 3724 | "ansi-str", 3725 | "ansitok", 3726 | "papergrid", 3727 | ] 3728 | 3729 | [[package]] 3730 | name = "tempfile" 3731 | version = "3.16.0" 3732 | source = "registry+https://github.com/rust-lang/crates.io-index" 3733 | checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" 3734 | dependencies = [ 3735 | "cfg-if", 3736 | "fastrand", 3737 | "getrandom 0.3.1", 3738 | "once_cell", 3739 | "rustix", 3740 | "windows-sys 0.59.0", 3741 | ] 3742 | 3743 | [[package]] 3744 | name = "terminal_size" 3745 | version = "0.4.1" 3746 | source = "registry+https://github.com/rust-lang/crates.io-index" 3747 | checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" 3748 | dependencies = [ 3749 | "rustix", 3750 | "windows-sys 0.59.0", 3751 | ] 3752 | 3753 | [[package]] 3754 | name = "textwrap" 3755 | version = "0.16.1" 3756 | source = "registry+https://github.com/rust-lang/crates.io-index" 3757 | checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" 3758 | dependencies = [ 3759 | "unicode-linebreak", 3760 | "unicode-width 0.1.11", 3761 | ] 3762 | 3763 | [[package]] 3764 | name = "thiserror" 3765 | version = "1.0.69" 3766 | source = "registry+https://github.com/rust-lang/crates.io-index" 3767 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 3768 | dependencies = [ 3769 | "thiserror-impl 1.0.69", 3770 | ] 3771 | 3772 | [[package]] 3773 | name = "thiserror" 3774 | version = "2.0.11" 3775 | source = "registry+https://github.com/rust-lang/crates.io-index" 3776 | checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" 3777 | dependencies = [ 3778 | "thiserror-impl 2.0.11", 3779 | ] 3780 | 3781 | [[package]] 3782 | name = "thiserror-impl" 3783 | version = "1.0.69" 3784 | source = "registry+https://github.com/rust-lang/crates.io-index" 3785 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 3786 | dependencies = [ 3787 | "proc-macro2", 3788 | "quote", 3789 | "syn", 3790 | ] 3791 | 3792 | [[package]] 3793 | name = "thiserror-impl" 3794 | version = "2.0.11" 3795 | source = "registry+https://github.com/rust-lang/crates.io-index" 3796 | checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" 3797 | dependencies = [ 3798 | "proc-macro2", 3799 | "quote", 3800 | "syn", 3801 | ] 3802 | 3803 | [[package]] 3804 | name = "thread_local" 3805 | version = "1.1.8" 3806 | source = "registry+https://github.com/rust-lang/crates.io-index" 3807 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 3808 | dependencies = [ 3809 | "cfg-if", 3810 | "once_cell", 3811 | ] 3812 | 3813 | [[package]] 3814 | name = "time" 3815 | version = "0.3.37" 3816 | source = "registry+https://github.com/rust-lang/crates.io-index" 3817 | checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" 3818 | dependencies = [ 3819 | "deranged", 3820 | "itoa", 3821 | "libc", 3822 | "num-conv", 3823 | "num_threads", 3824 | "powerfmt", 3825 | "serde", 3826 | "time-core", 3827 | "time-macros", 3828 | ] 3829 | 3830 | [[package]] 3831 | name = "time-core" 3832 | version = "0.1.2" 3833 | source = "registry+https://github.com/rust-lang/crates.io-index" 3834 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 3835 | 3836 | [[package]] 3837 | name = "time-macros" 3838 | version = "0.2.19" 3839 | source = "registry+https://github.com/rust-lang/crates.io-index" 3840 | checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" 3841 | dependencies = [ 3842 | "num-conv", 3843 | "time-core", 3844 | ] 3845 | 3846 | [[package]] 3847 | name = "tinystr" 3848 | version = "0.7.6" 3849 | source = "registry+https://github.com/rust-lang/crates.io-index" 3850 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 3851 | dependencies = [ 3852 | "displaydoc", 3853 | "zerovec", 3854 | ] 3855 | 3856 | [[package]] 3857 | name = "titlecase" 3858 | version = "3.5.0" 3859 | source = "registry+https://github.com/rust-lang/crates.io-index" 3860 | checksum = "a1fad07d425f7245932d6deb5009e2c83d9642617b47750ffc3363815e269435" 3861 | dependencies = [ 3862 | "regex", 3863 | ] 3864 | 3865 | [[package]] 3866 | name = "tokio" 3867 | version = "1.43.0" 3868 | source = "registry+https://github.com/rust-lang/crates.io-index" 3869 | checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" 3870 | dependencies = [ 3871 | "backtrace", 3872 | "bytes", 3873 | "libc", 3874 | "mio 1.0.3", 3875 | "parking_lot", 3876 | "pin-project-lite", 3877 | "signal-hook-registry", 3878 | "socket2", 3879 | "tokio-macros", 3880 | "windows-sys 0.52.0", 3881 | ] 3882 | 3883 | [[package]] 3884 | name = "tokio-macros" 3885 | version = "2.5.0" 3886 | source = "registry+https://github.com/rust-lang/crates.io-index" 3887 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 3888 | dependencies = [ 3889 | "proc-macro2", 3890 | "quote", 3891 | "syn", 3892 | ] 3893 | 3894 | [[package]] 3895 | name = "tokio-native-tls" 3896 | version = "0.3.1" 3897 | source = "registry+https://github.com/rust-lang/crates.io-index" 3898 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 3899 | dependencies = [ 3900 | "native-tls", 3901 | "tokio", 3902 | ] 3903 | 3904 | [[package]] 3905 | name = "tokio-rustls" 3906 | version = "0.26.1" 3907 | source = "registry+https://github.com/rust-lang/crates.io-index" 3908 | checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" 3909 | dependencies = [ 3910 | "rustls", 3911 | "tokio", 3912 | ] 3913 | 3914 | [[package]] 3915 | name = "tokio-stream" 3916 | version = "0.1.17" 3917 | source = "registry+https://github.com/rust-lang/crates.io-index" 3918 | checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" 3919 | dependencies = [ 3920 | "futures-core", 3921 | "pin-project-lite", 3922 | "tokio", 3923 | ] 3924 | 3925 | [[package]] 3926 | name = "tokio-test" 3927 | version = "0.4.4" 3928 | source = "registry+https://github.com/rust-lang/crates.io-index" 3929 | checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" 3930 | dependencies = [ 3931 | "async-stream", 3932 | "bytes", 3933 | "futures-core", 3934 | "tokio", 3935 | "tokio-stream", 3936 | ] 3937 | 3938 | [[package]] 3939 | name = "tokio-util" 3940 | version = "0.7.13" 3941 | source = "registry+https://github.com/rust-lang/crates.io-index" 3942 | checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" 3943 | dependencies = [ 3944 | "bytes", 3945 | "futures-core", 3946 | "futures-sink", 3947 | "pin-project-lite", 3948 | "tokio", 3949 | ] 3950 | 3951 | [[package]] 3952 | name = "toml" 3953 | version = "0.8.19" 3954 | source = "registry+https://github.com/rust-lang/crates.io-index" 3955 | checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" 3956 | dependencies = [ 3957 | "indexmap", 3958 | "serde", 3959 | "serde_spanned", 3960 | "toml_datetime", 3961 | "toml_edit", 3962 | ] 3963 | 3964 | [[package]] 3965 | name = "toml_datetime" 3966 | version = "0.6.8" 3967 | source = "registry+https://github.com/rust-lang/crates.io-index" 3968 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 3969 | dependencies = [ 3970 | "serde", 3971 | ] 3972 | 3973 | [[package]] 3974 | name = "toml_edit" 3975 | version = "0.22.22" 3976 | source = "registry+https://github.com/rust-lang/crates.io-index" 3977 | checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" 3978 | dependencies = [ 3979 | "indexmap", 3980 | "serde", 3981 | "serde_spanned", 3982 | "toml_datetime", 3983 | "winnow", 3984 | ] 3985 | 3986 | [[package]] 3987 | name = "tower" 3988 | version = "0.5.2" 3989 | source = "registry+https://github.com/rust-lang/crates.io-index" 3990 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 3991 | dependencies = [ 3992 | "futures-core", 3993 | "futures-util", 3994 | "pin-project-lite", 3995 | "sync_wrapper", 3996 | "tokio", 3997 | "tower-layer", 3998 | "tower-service", 3999 | ] 4000 | 4001 | [[package]] 4002 | name = "tower-layer" 4003 | version = "0.3.3" 4004 | source = "registry+https://github.com/rust-lang/crates.io-index" 4005 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 4006 | 4007 | [[package]] 4008 | name = "tower-service" 4009 | version = "0.3.3" 4010 | source = "registry+https://github.com/rust-lang/crates.io-index" 4011 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 4012 | 4013 | [[package]] 4014 | name = "tracing" 4015 | version = "0.1.41" 4016 | source = "registry+https://github.com/rust-lang/crates.io-index" 4017 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 4018 | dependencies = [ 4019 | "pin-project-lite", 4020 | "tracing-core", 4021 | ] 4022 | 4023 | [[package]] 4024 | name = "tracing-core" 4025 | version = "0.1.33" 4026 | source = "registry+https://github.com/rust-lang/crates.io-index" 4027 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 4028 | dependencies = [ 4029 | "once_cell", 4030 | ] 4031 | 4032 | [[package]] 4033 | name = "try-lock" 4034 | version = "0.2.5" 4035 | source = "registry+https://github.com/rust-lang/crates.io-index" 4036 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 4037 | 4038 | [[package]] 4039 | name = "typeid" 4040 | version = "1.0.2" 4041 | source = "registry+https://github.com/rust-lang/crates.io-index" 4042 | checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" 4043 | 4044 | [[package]] 4045 | name = "typenum" 4046 | version = "1.17.0" 4047 | source = "registry+https://github.com/rust-lang/crates.io-index" 4048 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 4049 | 4050 | [[package]] 4051 | name = "typetag" 4052 | version = "0.2.19" 4053 | source = "registry+https://github.com/rust-lang/crates.io-index" 4054 | checksum = "044fc3365ddd307c297fe0fe7b2e70588cdab4d0f62dc52055ca0d11b174cf0e" 4055 | dependencies = [ 4056 | "erased-serde", 4057 | "inventory", 4058 | "once_cell", 4059 | "serde", 4060 | "typetag-impl", 4061 | ] 4062 | 4063 | [[package]] 4064 | name = "typetag-impl" 4065 | version = "0.2.19" 4066 | source = "registry+https://github.com/rust-lang/crates.io-index" 4067 | checksum = "d9d30226ac9cbd2d1ff775f74e8febdab985dab14fb14aa2582c29a92d5555dc" 4068 | dependencies = [ 4069 | "proc-macro2", 4070 | "quote", 4071 | "syn", 4072 | ] 4073 | 4074 | [[package]] 4075 | name = "ucd-trie" 4076 | version = "0.1.7" 4077 | source = "registry+https://github.com/rust-lang/crates.io-index" 4078 | checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" 4079 | 4080 | [[package]] 4081 | name = "umask" 4082 | version = "2.1.0" 4083 | source = "registry+https://github.com/rust-lang/crates.io-index" 4084 | checksum = "ec9a46c2549e35c054e0ffe281a3a6ec0007793db4df106604d37ed3f4d73d1c" 4085 | dependencies = [ 4086 | "thiserror 1.0.69", 4087 | ] 4088 | 4089 | [[package]] 4090 | name = "unicase" 4091 | version = "2.8.1" 4092 | source = "registry+https://github.com/rust-lang/crates.io-index" 4093 | checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" 4094 | 4095 | [[package]] 4096 | name = "unicode-ident" 4097 | version = "1.0.15" 4098 | source = "registry+https://github.com/rust-lang/crates.io-index" 4099 | checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" 4100 | 4101 | [[package]] 4102 | name = "unicode-linebreak" 4103 | version = "0.1.5" 4104 | source = "registry+https://github.com/rust-lang/crates.io-index" 4105 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" 4106 | 4107 | [[package]] 4108 | name = "unicode-segmentation" 4109 | version = "1.12.0" 4110 | source = "registry+https://github.com/rust-lang/crates.io-index" 4111 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 4112 | 4113 | [[package]] 4114 | name = "unicode-width" 4115 | version = "0.1.11" 4116 | source = "registry+https://github.com/rust-lang/crates.io-index" 4117 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" 4118 | 4119 | [[package]] 4120 | name = "unicode-width" 4121 | version = "0.2.0" 4122 | source = "registry+https://github.com/rust-lang/crates.io-index" 4123 | checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" 4124 | 4125 | [[package]] 4126 | name = "unicode-xid" 4127 | version = "0.2.6" 4128 | source = "registry+https://github.com/rust-lang/crates.io-index" 4129 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 4130 | 4131 | [[package]] 4132 | name = "unsafe-libyaml" 4133 | version = "0.2.11" 4134 | source = "registry+https://github.com/rust-lang/crates.io-index" 4135 | checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" 4136 | 4137 | [[package]] 4138 | name = "untrusted" 4139 | version = "0.9.0" 4140 | source = "registry+https://github.com/rust-lang/crates.io-index" 4141 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 4142 | 4143 | [[package]] 4144 | name = "update-informer" 4145 | version = "1.2.0" 4146 | source = "registry+https://github.com/rust-lang/crates.io-index" 4147 | checksum = "53813bf5d5f0d8430794f8cc48e99521cc9e298066958d16383ccb8b39d182a7" 4148 | dependencies = [ 4149 | "etcetera", 4150 | "reqwest", 4151 | "semver", 4152 | "serde", 4153 | "serde_json", 4154 | "ureq", 4155 | ] 4156 | 4157 | [[package]] 4158 | name = "ureq" 4159 | version = "2.12.1" 4160 | source = "registry+https://github.com/rust-lang/crates.io-index" 4161 | checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" 4162 | dependencies = [ 4163 | "base64", 4164 | "encoding_rs", 4165 | "flate2", 4166 | "log", 4167 | "native-tls", 4168 | "once_cell", 4169 | "serde", 4170 | "serde_json", 4171 | "url", 4172 | ] 4173 | 4174 | [[package]] 4175 | name = "url" 4176 | version = "2.5.4" 4177 | source = "registry+https://github.com/rust-lang/crates.io-index" 4178 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 4179 | dependencies = [ 4180 | "form_urlencoded", 4181 | "idna", 4182 | "percent-encoding", 4183 | ] 4184 | 4185 | [[package]] 4186 | name = "utf16_iter" 4187 | version = "1.0.5" 4188 | source = "registry+https://github.com/rust-lang/crates.io-index" 4189 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 4190 | 4191 | [[package]] 4192 | name = "utf8_iter" 4193 | version = "1.0.4" 4194 | source = "registry+https://github.com/rust-lang/crates.io-index" 4195 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 4196 | 4197 | [[package]] 4198 | name = "utf8parse" 4199 | version = "0.2.2" 4200 | source = "registry+https://github.com/rust-lang/crates.io-index" 4201 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 4202 | 4203 | [[package]] 4204 | name = "uu_cp" 4205 | version = "0.0.29" 4206 | source = "registry+https://github.com/rust-lang/crates.io-index" 4207 | checksum = "235439f8efcff799cbdb90992cb5b1845dce903c1569efc8d9b46417c83f5aa8" 4208 | dependencies = [ 4209 | "clap", 4210 | "filetime", 4211 | "indicatif", 4212 | "libc", 4213 | "quick-error", 4214 | "uucore", 4215 | "walkdir", 4216 | "xattr", 4217 | ] 4218 | 4219 | [[package]] 4220 | name = "uu_mkdir" 4221 | version = "0.0.29" 4222 | source = "registry+https://github.com/rust-lang/crates.io-index" 4223 | checksum = "ea0a30620d88a7ea16b522e1fe63ebb61f87f05fd63ade00938a024807356952" 4224 | dependencies = [ 4225 | "clap", 4226 | "uucore", 4227 | ] 4228 | 4229 | [[package]] 4230 | name = "uu_mktemp" 4231 | version = "0.0.29" 4232 | source = "registry+https://github.com/rust-lang/crates.io-index" 4233 | checksum = "e1db7648ff064cdfe8a0e6ef9546de3b03e34cefa270b783de7736a8470473cc" 4234 | dependencies = [ 4235 | "clap", 4236 | "rand", 4237 | "tempfile", 4238 | "uucore", 4239 | ] 4240 | 4241 | [[package]] 4242 | name = "uu_mv" 4243 | version = "0.0.29" 4244 | source = "registry+https://github.com/rust-lang/crates.io-index" 4245 | checksum = "92ab8c17ac7153adaa0176924319827cfb240cf48e4260283facfdb37e776071" 4246 | dependencies = [ 4247 | "clap", 4248 | "fs_extra", 4249 | "indicatif", 4250 | "uucore", 4251 | ] 4252 | 4253 | [[package]] 4254 | name = "uu_touch" 4255 | version = "0.0.29" 4256 | source = "registry+https://github.com/rust-lang/crates.io-index" 4257 | checksum = "3adc774c7961272cd2feeb95f2bf2e0b8f7b8ccd5fbcf49727d0de1eab804b67" 4258 | dependencies = [ 4259 | "chrono", 4260 | "clap", 4261 | "filetime", 4262 | "parse_datetime", 4263 | "uucore", 4264 | "windows-sys 0.59.0", 4265 | ] 4266 | 4267 | [[package]] 4268 | name = "uu_uname" 4269 | version = "0.0.29" 4270 | source = "registry+https://github.com/rust-lang/crates.io-index" 4271 | checksum = "95a942626aec03d4f4d972b10e00f9ddcdced1933658076eccafea5a20fdafb8" 4272 | dependencies = [ 4273 | "clap", 4274 | "platform-info", 4275 | "uucore", 4276 | ] 4277 | 4278 | [[package]] 4279 | name = "uu_whoami" 4280 | version = "0.0.29" 4281 | source = "registry+https://github.com/rust-lang/crates.io-index" 4282 | checksum = "a812f7a838c9375c15ed13b66048df2c632c1ac3ec613dabb28c648019c6d018" 4283 | dependencies = [ 4284 | "clap", 4285 | "libc", 4286 | "uucore", 4287 | "windows-sys 0.59.0", 4288 | ] 4289 | 4290 | [[package]] 4291 | name = "uucore" 4292 | version = "0.0.29" 4293 | source = "registry+https://github.com/rust-lang/crates.io-index" 4294 | checksum = "50e0dc1598d959a08f24cea4d9e992f7ca874bd4ac80746683272afd37603b5e" 4295 | dependencies = [ 4296 | "clap", 4297 | "dunce", 4298 | "glob", 4299 | "lazy_static", 4300 | "libc", 4301 | "nix", 4302 | "number_prefix", 4303 | "once_cell", 4304 | "os_display", 4305 | "uucore_procs", 4306 | "walkdir", 4307 | "wild", 4308 | "winapi-util", 4309 | "windows-sys 0.59.0", 4310 | "xattr", 4311 | ] 4312 | 4313 | [[package]] 4314 | name = "uucore_procs" 4315 | version = "0.0.29" 4316 | source = "registry+https://github.com/rust-lang/crates.io-index" 4317 | checksum = "27d3de33ab2b56c0437cca084a2aeb1d46c56d138ab6341c009a90018a9a1c5f" 4318 | dependencies = [ 4319 | "proc-macro2", 4320 | "quote", 4321 | "uuhelp_parser", 4322 | ] 4323 | 4324 | [[package]] 4325 | name = "uuhelp_parser" 4326 | version = "0.0.29" 4327 | source = "registry+https://github.com/rust-lang/crates.io-index" 4328 | checksum = "0cf4c8b31abfb5dc79940d6ca8000a1a6aa42f38711cdeaacb95850c69924cbc" 4329 | 4330 | [[package]] 4331 | name = "uuid" 4332 | version = "1.12.1" 4333 | source = "registry+https://github.com/rust-lang/crates.io-index" 4334 | checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" 4335 | dependencies = [ 4336 | "atomic", 4337 | "getrandom 0.2.15", 4338 | "md-5", 4339 | "sha1_smol", 4340 | ] 4341 | 4342 | [[package]] 4343 | name = "v_htmlescape" 4344 | version = "0.15.8" 4345 | source = "registry+https://github.com/rust-lang/crates.io-index" 4346 | checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" 4347 | 4348 | [[package]] 4349 | name = "vcpkg" 4350 | version = "0.2.15" 4351 | source = "registry+https://github.com/rust-lang/crates.io-index" 4352 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 4353 | 4354 | [[package]] 4355 | name = "version_check" 4356 | version = "0.9.5" 4357 | source = "registry+https://github.com/rust-lang/crates.io-index" 4358 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 4359 | 4360 | [[package]] 4361 | name = "vte" 4362 | version = "0.10.1" 4363 | source = "registry+https://github.com/rust-lang/crates.io-index" 4364 | checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" 4365 | dependencies = [ 4366 | "arrayvec 0.5.2", 4367 | "utf8parse", 4368 | "vte_generate_state_changes", 4369 | ] 4370 | 4371 | [[package]] 4372 | name = "vte" 4373 | version = "0.14.1" 4374 | source = "registry+https://github.com/rust-lang/crates.io-index" 4375 | checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" 4376 | dependencies = [ 4377 | "memchr", 4378 | ] 4379 | 4380 | [[package]] 4381 | name = "vte_generate_state_changes" 4382 | version = "0.1.2" 4383 | source = "registry+https://github.com/rust-lang/crates.io-index" 4384 | checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" 4385 | dependencies = [ 4386 | "proc-macro2", 4387 | "quote", 4388 | ] 4389 | 4390 | [[package]] 4391 | name = "walkdir" 4392 | version = "2.5.0" 4393 | source = "registry+https://github.com/rust-lang/crates.io-index" 4394 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 4395 | dependencies = [ 4396 | "same-file", 4397 | "winapi-util", 4398 | ] 4399 | 4400 | [[package]] 4401 | name = "want" 4402 | version = "0.3.1" 4403 | source = "registry+https://github.com/rust-lang/crates.io-index" 4404 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 4405 | dependencies = [ 4406 | "try-lock", 4407 | ] 4408 | 4409 | [[package]] 4410 | name = "wasi" 4411 | version = "0.11.0+wasi-snapshot-preview1" 4412 | source = "registry+https://github.com/rust-lang/crates.io-index" 4413 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 4414 | 4415 | [[package]] 4416 | name = "wasi" 4417 | version = "0.13.3+wasi-0.2.2" 4418 | source = "registry+https://github.com/rust-lang/crates.io-index" 4419 | checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" 4420 | dependencies = [ 4421 | "wit-bindgen-rt", 4422 | ] 4423 | 4424 | [[package]] 4425 | name = "wasm-bindgen" 4426 | version = "0.2.100" 4427 | source = "registry+https://github.com/rust-lang/crates.io-index" 4428 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 4429 | dependencies = [ 4430 | "cfg-if", 4431 | "once_cell", 4432 | "rustversion", 4433 | "wasm-bindgen-macro", 4434 | ] 4435 | 4436 | [[package]] 4437 | name = "wasm-bindgen-backend" 4438 | version = "0.2.100" 4439 | source = "registry+https://github.com/rust-lang/crates.io-index" 4440 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 4441 | dependencies = [ 4442 | "bumpalo", 4443 | "log", 4444 | "proc-macro2", 4445 | "quote", 4446 | "syn", 4447 | "wasm-bindgen-shared", 4448 | ] 4449 | 4450 | [[package]] 4451 | name = "wasm-bindgen-futures" 4452 | version = "0.4.50" 4453 | source = "registry+https://github.com/rust-lang/crates.io-index" 4454 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 4455 | dependencies = [ 4456 | "cfg-if", 4457 | "js-sys", 4458 | "once_cell", 4459 | "wasm-bindgen", 4460 | "web-sys", 4461 | ] 4462 | 4463 | [[package]] 4464 | name = "wasm-bindgen-macro" 4465 | version = "0.2.100" 4466 | source = "registry+https://github.com/rust-lang/crates.io-index" 4467 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 4468 | dependencies = [ 4469 | "quote", 4470 | "wasm-bindgen-macro-support", 4471 | ] 4472 | 4473 | [[package]] 4474 | name = "wasm-bindgen-macro-support" 4475 | version = "0.2.100" 4476 | source = "registry+https://github.com/rust-lang/crates.io-index" 4477 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 4478 | dependencies = [ 4479 | "proc-macro2", 4480 | "quote", 4481 | "syn", 4482 | "wasm-bindgen-backend", 4483 | "wasm-bindgen-shared", 4484 | ] 4485 | 4486 | [[package]] 4487 | name = "wasm-bindgen-shared" 4488 | version = "0.2.100" 4489 | source = "registry+https://github.com/rust-lang/crates.io-index" 4490 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 4491 | dependencies = [ 4492 | "unicode-ident", 4493 | ] 4494 | 4495 | [[package]] 4496 | name = "wax" 4497 | version = "0.6.0" 4498 | source = "registry+https://github.com/rust-lang/crates.io-index" 4499 | checksum = "8d12a78aa0bab22d2f26ed1a96df7ab58e8a93506a3e20adb47c51a93b4e1357" 4500 | dependencies = [ 4501 | "const_format", 4502 | "itertools 0.11.0", 4503 | "nom", 4504 | "pori", 4505 | "regex", 4506 | "thiserror 1.0.69", 4507 | "walkdir", 4508 | ] 4509 | 4510 | [[package]] 4511 | name = "web-sys" 4512 | version = "0.3.77" 4513 | source = "registry+https://github.com/rust-lang/crates.io-index" 4514 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 4515 | dependencies = [ 4516 | "js-sys", 4517 | "wasm-bindgen", 4518 | ] 4519 | 4520 | [[package]] 4521 | name = "web-time" 4522 | version = "1.1.0" 4523 | source = "registry+https://github.com/rust-lang/crates.io-index" 4524 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 4525 | dependencies = [ 4526 | "js-sys", 4527 | "wasm-bindgen", 4528 | ] 4529 | 4530 | [[package]] 4531 | name = "which" 4532 | version = "4.4.2" 4533 | source = "registry+https://github.com/rust-lang/crates.io-index" 4534 | checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" 4535 | dependencies = [ 4536 | "either", 4537 | "home", 4538 | "once_cell", 4539 | "rustix", 4540 | ] 4541 | 4542 | [[package]] 4543 | name = "which" 4544 | version = "7.0.1" 4545 | source = "registry+https://github.com/rust-lang/crates.io-index" 4546 | checksum = "fb4a9e33648339dc1642b0e36e21b3385e6148e289226f657c809dee59df5028" 4547 | dependencies = [ 4548 | "either", 4549 | "env_home", 4550 | "rustix", 4551 | "winsafe", 4552 | ] 4553 | 4554 | [[package]] 4555 | name = "wild" 4556 | version = "2.2.1" 4557 | source = "registry+https://github.com/rust-lang/crates.io-index" 4558 | checksum = "a3131afc8c575281e1e80f36ed6a092aa502c08b18ed7524e86fbbb12bb410e1" 4559 | dependencies = [ 4560 | "glob", 4561 | ] 4562 | 4563 | [[package]] 4564 | name = "winapi" 4565 | version = "0.3.9" 4566 | source = "registry+https://github.com/rust-lang/crates.io-index" 4567 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 4568 | dependencies = [ 4569 | "winapi-i686-pc-windows-gnu", 4570 | "winapi-x86_64-pc-windows-gnu", 4571 | ] 4572 | 4573 | [[package]] 4574 | name = "winapi-i686-pc-windows-gnu" 4575 | version = "0.4.0" 4576 | source = "registry+https://github.com/rust-lang/crates.io-index" 4577 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 4578 | 4579 | [[package]] 4580 | name = "winapi-util" 4581 | version = "0.1.9" 4582 | source = "registry+https://github.com/rust-lang/crates.io-index" 4583 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 4584 | dependencies = [ 4585 | "windows-sys 0.59.0", 4586 | ] 4587 | 4588 | [[package]] 4589 | name = "winapi-x86_64-pc-windows-gnu" 4590 | version = "0.4.0" 4591 | source = "registry+https://github.com/rust-lang/crates.io-index" 4592 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 4593 | 4594 | [[package]] 4595 | name = "windows" 4596 | version = "0.56.0" 4597 | source = "registry+https://github.com/rust-lang/crates.io-index" 4598 | checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" 4599 | dependencies = [ 4600 | "windows-core 0.56.0", 4601 | "windows-targets 0.52.6", 4602 | ] 4603 | 4604 | [[package]] 4605 | name = "windows" 4606 | version = "0.57.0" 4607 | source = "registry+https://github.com/rust-lang/crates.io-index" 4608 | checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" 4609 | dependencies = [ 4610 | "windows-core 0.57.0", 4611 | "windows-targets 0.52.6", 4612 | ] 4613 | 4614 | [[package]] 4615 | name = "windows-core" 4616 | version = "0.52.0" 4617 | source = "registry+https://github.com/rust-lang/crates.io-index" 4618 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 4619 | dependencies = [ 4620 | "windows-targets 0.52.6", 4621 | ] 4622 | 4623 | [[package]] 4624 | name = "windows-core" 4625 | version = "0.56.0" 4626 | source = "registry+https://github.com/rust-lang/crates.io-index" 4627 | checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" 4628 | dependencies = [ 4629 | "windows-implement 0.56.0", 4630 | "windows-interface 0.56.0", 4631 | "windows-result 0.1.2", 4632 | "windows-targets 0.52.6", 4633 | ] 4634 | 4635 | [[package]] 4636 | name = "windows-core" 4637 | version = "0.57.0" 4638 | source = "registry+https://github.com/rust-lang/crates.io-index" 4639 | checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" 4640 | dependencies = [ 4641 | "windows-implement 0.57.0", 4642 | "windows-interface 0.57.0", 4643 | "windows-result 0.1.2", 4644 | "windows-targets 0.52.6", 4645 | ] 4646 | 4647 | [[package]] 4648 | name = "windows-implement" 4649 | version = "0.56.0" 4650 | source = "registry+https://github.com/rust-lang/crates.io-index" 4651 | checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" 4652 | dependencies = [ 4653 | "proc-macro2", 4654 | "quote", 4655 | "syn", 4656 | ] 4657 | 4658 | [[package]] 4659 | name = "windows-implement" 4660 | version = "0.57.0" 4661 | source = "registry+https://github.com/rust-lang/crates.io-index" 4662 | checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" 4663 | dependencies = [ 4664 | "proc-macro2", 4665 | "quote", 4666 | "syn", 4667 | ] 4668 | 4669 | [[package]] 4670 | name = "windows-interface" 4671 | version = "0.56.0" 4672 | source = "registry+https://github.com/rust-lang/crates.io-index" 4673 | checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" 4674 | dependencies = [ 4675 | "proc-macro2", 4676 | "quote", 4677 | "syn", 4678 | ] 4679 | 4680 | [[package]] 4681 | name = "windows-interface" 4682 | version = "0.57.0" 4683 | source = "registry+https://github.com/rust-lang/crates.io-index" 4684 | checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" 4685 | dependencies = [ 4686 | "proc-macro2", 4687 | "quote", 4688 | "syn", 4689 | ] 4690 | 4691 | [[package]] 4692 | name = "windows-link" 4693 | version = "0.1.1" 4694 | source = "registry+https://github.com/rust-lang/crates.io-index" 4695 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 4696 | 4697 | [[package]] 4698 | name = "windows-registry" 4699 | version = "0.4.0" 4700 | source = "registry+https://github.com/rust-lang/crates.io-index" 4701 | checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 4702 | dependencies = [ 4703 | "windows-result 0.3.2", 4704 | "windows-strings", 4705 | "windows-targets 0.53.0", 4706 | ] 4707 | 4708 | [[package]] 4709 | name = "windows-result" 4710 | version = "0.1.2" 4711 | source = "registry+https://github.com/rust-lang/crates.io-index" 4712 | checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" 4713 | dependencies = [ 4714 | "windows-targets 0.52.6", 4715 | ] 4716 | 4717 | [[package]] 4718 | name = "windows-result" 4719 | version = "0.3.2" 4720 | source = "registry+https://github.com/rust-lang/crates.io-index" 4721 | checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 4722 | dependencies = [ 4723 | "windows-link", 4724 | ] 4725 | 4726 | [[package]] 4727 | name = "windows-strings" 4728 | version = "0.3.1" 4729 | source = "registry+https://github.com/rust-lang/crates.io-index" 4730 | checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 4731 | dependencies = [ 4732 | "windows-link", 4733 | ] 4734 | 4735 | [[package]] 4736 | name = "windows-sys" 4737 | version = "0.48.0" 4738 | source = "registry+https://github.com/rust-lang/crates.io-index" 4739 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 4740 | dependencies = [ 4741 | "windows-targets 0.48.5", 4742 | ] 4743 | 4744 | [[package]] 4745 | name = "windows-sys" 4746 | version = "0.52.0" 4747 | source = "registry+https://github.com/rust-lang/crates.io-index" 4748 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 4749 | dependencies = [ 4750 | "windows-targets 0.52.6", 4751 | ] 4752 | 4753 | [[package]] 4754 | name = "windows-sys" 4755 | version = "0.59.0" 4756 | source = "registry+https://github.com/rust-lang/crates.io-index" 4757 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 4758 | dependencies = [ 4759 | "windows-targets 0.52.6", 4760 | ] 4761 | 4762 | [[package]] 4763 | name = "windows-targets" 4764 | version = "0.48.5" 4765 | source = "registry+https://github.com/rust-lang/crates.io-index" 4766 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 4767 | dependencies = [ 4768 | "windows_aarch64_gnullvm 0.48.5", 4769 | "windows_aarch64_msvc 0.48.5", 4770 | "windows_i686_gnu 0.48.5", 4771 | "windows_i686_msvc 0.48.5", 4772 | "windows_x86_64_gnu 0.48.5", 4773 | "windows_x86_64_gnullvm 0.48.5", 4774 | "windows_x86_64_msvc 0.48.5", 4775 | ] 4776 | 4777 | [[package]] 4778 | name = "windows-targets" 4779 | version = "0.52.6" 4780 | source = "registry+https://github.com/rust-lang/crates.io-index" 4781 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 4782 | dependencies = [ 4783 | "windows_aarch64_gnullvm 0.52.6", 4784 | "windows_aarch64_msvc 0.52.6", 4785 | "windows_i686_gnu 0.52.6", 4786 | "windows_i686_gnullvm 0.52.6", 4787 | "windows_i686_msvc 0.52.6", 4788 | "windows_x86_64_gnu 0.52.6", 4789 | "windows_x86_64_gnullvm 0.52.6", 4790 | "windows_x86_64_msvc 0.52.6", 4791 | ] 4792 | 4793 | [[package]] 4794 | name = "windows-targets" 4795 | version = "0.53.0" 4796 | source = "registry+https://github.com/rust-lang/crates.io-index" 4797 | checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" 4798 | dependencies = [ 4799 | "windows_aarch64_gnullvm 0.53.0", 4800 | "windows_aarch64_msvc 0.53.0", 4801 | "windows_i686_gnu 0.53.0", 4802 | "windows_i686_gnullvm 0.53.0", 4803 | "windows_i686_msvc 0.53.0", 4804 | "windows_x86_64_gnu 0.53.0", 4805 | "windows_x86_64_gnullvm 0.53.0", 4806 | "windows_x86_64_msvc 0.53.0", 4807 | ] 4808 | 4809 | [[package]] 4810 | name = "windows_aarch64_gnullvm" 4811 | version = "0.48.5" 4812 | source = "registry+https://github.com/rust-lang/crates.io-index" 4813 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 4814 | 4815 | [[package]] 4816 | name = "windows_aarch64_gnullvm" 4817 | version = "0.52.6" 4818 | source = "registry+https://github.com/rust-lang/crates.io-index" 4819 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 4820 | 4821 | [[package]] 4822 | name = "windows_aarch64_gnullvm" 4823 | version = "0.53.0" 4824 | source = "registry+https://github.com/rust-lang/crates.io-index" 4825 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 4826 | 4827 | [[package]] 4828 | name = "windows_aarch64_msvc" 4829 | version = "0.48.5" 4830 | source = "registry+https://github.com/rust-lang/crates.io-index" 4831 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 4832 | 4833 | [[package]] 4834 | name = "windows_aarch64_msvc" 4835 | version = "0.52.6" 4836 | source = "registry+https://github.com/rust-lang/crates.io-index" 4837 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 4838 | 4839 | [[package]] 4840 | name = "windows_aarch64_msvc" 4841 | version = "0.53.0" 4842 | source = "registry+https://github.com/rust-lang/crates.io-index" 4843 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 4844 | 4845 | [[package]] 4846 | name = "windows_i686_gnu" 4847 | version = "0.48.5" 4848 | source = "registry+https://github.com/rust-lang/crates.io-index" 4849 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 4850 | 4851 | [[package]] 4852 | name = "windows_i686_gnu" 4853 | version = "0.52.6" 4854 | source = "registry+https://github.com/rust-lang/crates.io-index" 4855 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 4856 | 4857 | [[package]] 4858 | name = "windows_i686_gnu" 4859 | version = "0.53.0" 4860 | source = "registry+https://github.com/rust-lang/crates.io-index" 4861 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 4862 | 4863 | [[package]] 4864 | name = "windows_i686_gnullvm" 4865 | version = "0.52.6" 4866 | source = "registry+https://github.com/rust-lang/crates.io-index" 4867 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 4868 | 4869 | [[package]] 4870 | name = "windows_i686_gnullvm" 4871 | version = "0.53.0" 4872 | source = "registry+https://github.com/rust-lang/crates.io-index" 4873 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 4874 | 4875 | [[package]] 4876 | name = "windows_i686_msvc" 4877 | version = "0.48.5" 4878 | source = "registry+https://github.com/rust-lang/crates.io-index" 4879 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 4880 | 4881 | [[package]] 4882 | name = "windows_i686_msvc" 4883 | version = "0.52.6" 4884 | source = "registry+https://github.com/rust-lang/crates.io-index" 4885 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 4886 | 4887 | [[package]] 4888 | name = "windows_i686_msvc" 4889 | version = "0.53.0" 4890 | source = "registry+https://github.com/rust-lang/crates.io-index" 4891 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 4892 | 4893 | [[package]] 4894 | name = "windows_x86_64_gnu" 4895 | version = "0.48.5" 4896 | source = "registry+https://github.com/rust-lang/crates.io-index" 4897 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 4898 | 4899 | [[package]] 4900 | name = "windows_x86_64_gnu" 4901 | version = "0.52.6" 4902 | source = "registry+https://github.com/rust-lang/crates.io-index" 4903 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 4904 | 4905 | [[package]] 4906 | name = "windows_x86_64_gnu" 4907 | version = "0.53.0" 4908 | source = "registry+https://github.com/rust-lang/crates.io-index" 4909 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 4910 | 4911 | [[package]] 4912 | name = "windows_x86_64_gnullvm" 4913 | version = "0.48.5" 4914 | source = "registry+https://github.com/rust-lang/crates.io-index" 4915 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 4916 | 4917 | [[package]] 4918 | name = "windows_x86_64_gnullvm" 4919 | version = "0.52.6" 4920 | source = "registry+https://github.com/rust-lang/crates.io-index" 4921 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 4922 | 4923 | [[package]] 4924 | name = "windows_x86_64_gnullvm" 4925 | version = "0.53.0" 4926 | source = "registry+https://github.com/rust-lang/crates.io-index" 4927 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 4928 | 4929 | [[package]] 4930 | name = "windows_x86_64_msvc" 4931 | version = "0.48.5" 4932 | source = "registry+https://github.com/rust-lang/crates.io-index" 4933 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 4934 | 4935 | [[package]] 4936 | name = "windows_x86_64_msvc" 4937 | version = "0.52.6" 4938 | source = "registry+https://github.com/rust-lang/crates.io-index" 4939 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 4940 | 4941 | [[package]] 4942 | name = "windows_x86_64_msvc" 4943 | version = "0.53.0" 4944 | source = "registry+https://github.com/rust-lang/crates.io-index" 4945 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 4946 | 4947 | [[package]] 4948 | name = "winnow" 4949 | version = "0.6.24" 4950 | source = "registry+https://github.com/rust-lang/crates.io-index" 4951 | checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" 4952 | dependencies = [ 4953 | "memchr", 4954 | ] 4955 | 4956 | [[package]] 4957 | name = "winreg" 4958 | version = "0.52.0" 4959 | source = "registry+https://github.com/rust-lang/crates.io-index" 4960 | checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" 4961 | dependencies = [ 4962 | "cfg-if", 4963 | "windows-sys 0.48.0", 4964 | ] 4965 | 4966 | [[package]] 4967 | name = "winsafe" 4968 | version = "0.0.19" 4969 | source = "registry+https://github.com/rust-lang/crates.io-index" 4970 | checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" 4971 | 4972 | [[package]] 4973 | name = "wit-bindgen-rt" 4974 | version = "0.33.0" 4975 | source = "registry+https://github.com/rust-lang/crates.io-index" 4976 | checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" 4977 | dependencies = [ 4978 | "bitflags 2.8.0", 4979 | ] 4980 | 4981 | [[package]] 4982 | name = "write16" 4983 | version = "1.0.0" 4984 | source = "registry+https://github.com/rust-lang/crates.io-index" 4985 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 4986 | 4987 | [[package]] 4988 | name = "writeable" 4989 | version = "0.5.5" 4990 | source = "registry+https://github.com/rust-lang/crates.io-index" 4991 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 4992 | 4993 | [[package]] 4994 | name = "xattr" 4995 | version = "1.4.0" 4996 | source = "registry+https://github.com/rust-lang/crates.io-index" 4997 | checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909" 4998 | dependencies = [ 4999 | "libc", 5000 | "linux-raw-sys", 5001 | "rustix", 5002 | ] 5003 | 5004 | [[package]] 5005 | name = "yoke" 5006 | version = "0.7.5" 5007 | source = "registry+https://github.com/rust-lang/crates.io-index" 5008 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 5009 | dependencies = [ 5010 | "serde", 5011 | "stable_deref_trait", 5012 | "yoke-derive", 5013 | "zerofrom", 5014 | ] 5015 | 5016 | [[package]] 5017 | name = "yoke-derive" 5018 | version = "0.7.5" 5019 | source = "registry+https://github.com/rust-lang/crates.io-index" 5020 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 5021 | dependencies = [ 5022 | "proc-macro2", 5023 | "quote", 5024 | "syn", 5025 | "synstructure", 5026 | ] 5027 | 5028 | [[package]] 5029 | name = "zerocopy" 5030 | version = "0.7.35" 5031 | source = "registry+https://github.com/rust-lang/crates.io-index" 5032 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 5033 | dependencies = [ 5034 | "byteorder", 5035 | "zerocopy-derive", 5036 | ] 5037 | 5038 | [[package]] 5039 | name = "zerocopy-derive" 5040 | version = "0.7.35" 5041 | source = "registry+https://github.com/rust-lang/crates.io-index" 5042 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 5043 | dependencies = [ 5044 | "proc-macro2", 5045 | "quote", 5046 | "syn", 5047 | ] 5048 | 5049 | [[package]] 5050 | name = "zerofrom" 5051 | version = "0.1.5" 5052 | source = "registry+https://github.com/rust-lang/crates.io-index" 5053 | checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" 5054 | dependencies = [ 5055 | "zerofrom-derive", 5056 | ] 5057 | 5058 | [[package]] 5059 | name = "zerofrom-derive" 5060 | version = "0.1.5" 5061 | source = "registry+https://github.com/rust-lang/crates.io-index" 5062 | checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" 5063 | dependencies = [ 5064 | "proc-macro2", 5065 | "quote", 5066 | "syn", 5067 | "synstructure", 5068 | ] 5069 | 5070 | [[package]] 5071 | name = "zeroize" 5072 | version = "1.8.1" 5073 | source = "registry+https://github.com/rust-lang/crates.io-index" 5074 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 5075 | 5076 | [[package]] 5077 | name = "zerovec" 5078 | version = "0.10.4" 5079 | source = "registry+https://github.com/rust-lang/crates.io-index" 5080 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 5081 | dependencies = [ 5082 | "yoke", 5083 | "zerofrom", 5084 | "zerovec-derive", 5085 | ] 5086 | 5087 | [[package]] 5088 | name = "zerovec-derive" 5089 | version = "0.10.3" 5090 | source = "registry+https://github.com/rust-lang/crates.io-index" 5091 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 5092 | dependencies = [ 5093 | "proc-macro2", 5094 | "quote", 5095 | "syn", 5096 | ] 5097 | 5098 | [[package]] 5099 | name = "zip" 5100 | version = "2.2.2" 5101 | source = "registry+https://github.com/rust-lang/crates.io-index" 5102 | checksum = "ae9c1ea7b3a5e1f4b922ff856a129881167511563dc219869afe3787fc0c1a45" 5103 | dependencies = [ 5104 | "arbitrary", 5105 | "crc32fast", 5106 | "crossbeam-utils", 5107 | "displaydoc", 5108 | "flate2", 5109 | "indexmap", 5110 | "memchr", 5111 | "thiserror 2.0.11", 5112 | "zopfli", 5113 | ] 5114 | 5115 | [[package]] 5116 | name = "zopfli" 5117 | version = "0.8.1" 5118 | source = "registry+https://github.com/rust-lang/crates.io-index" 5119 | checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" 5120 | dependencies = [ 5121 | "bumpalo", 5122 | "crc32fast", 5123 | "lockfree-object-pool", 5124 | "log", 5125 | "once_cell", 5126 | "simd-adler32", 5127 | ] 5128 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "http-nu" 3 | version = "0.4.2" 4 | edition = "2021" 5 | description = "Serve a Nushell closure over HTTP." 6 | license = "MIT" 7 | repository = "https://github.com/cablehead/http-nu" 8 | readme = "README.md" 9 | homepage = "https://github.com/cablehead/http-nu" 10 | keywords = ["http", "shell", "nushell", "server"] 11 | categories = ["web-programming", "command-line-utilities"] 12 | 13 | [[bin]] 14 | name = "http-nu" 15 | path = "src/main.rs" 16 | 17 | [dependencies] 18 | clap = { version = "4", features = ["derive"] } 19 | 20 | serde = { version = "1", features = ["derive"] } 21 | serde_json = "1" 22 | http-serde = "2.1.1" 23 | 24 | http = "1.1.0" 25 | http-body-util = "0.1" 26 | hyper = { version = "1", features = ["full"] } 27 | hyper-util = { version = "0.1", features = ["full"] } 28 | tokio = { version = "1", features = ["full"] } 29 | tokio-stream = "0.1" 30 | tokio-util = { version = "0.7", features = ["io"] } 31 | 32 | bytes = "1.6.0" 33 | url = "2.5.0" 34 | 35 | nu-cli = "0.103.0" 36 | nu-cmd-lang = "0.103.0" 37 | nu-cmd-extra = "0.103.0" 38 | nu-command = "0.103.0" 39 | nu-engine = "0.103.0" 40 | nu-parser = "0.103.0" 41 | nu-protocol = "0.103.0" 42 | tokio-rustls = "0.26.1" 43 | rustls = "0.23.23" 44 | rustls-pemfile = "2.2.0" 45 | hyper-staticfile = "0.10.1" 46 | scru128 = { version = "3", features = ["serde"] } 47 | 48 | [dev-dependencies] 49 | tokio-test = "0.4" 50 | tempfile = "3.10.1" 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Andy Gayton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## http-nu [![Cross-platform CI](https://github.com/cablehead/http-nu/actions/workflows/ci.yml/badge.svg)](https://github.com/cablehead/http-nu/actions/workflows/ci.yml) 2 | 3 | From shell to web: `http-nu` serves your [Nushell](https://www.nushell.sh) closure over HTTP. 4 | 5 | ## Install 6 | 7 | ```bash 8 | cargo install http-nu --locked 9 | ``` 10 | 11 | ## Overview 12 | 13 | ### GET: Hello world 14 | 15 | ```bash 16 | $ http-nu :3001 '{|req| "Hello world"}' 17 | $ curl -s localhost:3001 18 | Hello world 19 | ``` 20 | 21 | ### Reading closures from stdin 22 | 23 | You can also pass `-` as the closure argument to read the closure from stdin: 24 | 25 | ```bash 26 | $ echo '{|req| "Hello from stdin"}' | http-nu :3001 - 27 | $ curl -s localhost:3001 28 | Hello from stdin 29 | ``` 30 | 31 | This is especially useful for more complex closures stored in files: 32 | 33 | ```bash 34 | $ cat handler.nu | http-nu :3001 - 35 | ``` 36 | 37 | Check out the [`examples/basic.nu`](examples/basic.nu) file in the repository for a complete example that implements a mini web server with multiple routes, form handling, and streaming responses. 38 | 39 | You can listen to UNIX domain sockets as well 40 | 41 | ```bash 42 | $ http-nu ./sock '{|req| "Hello world"}' 43 | $ curl -s --unix-socket ./sock localhost 44 | Hello world 45 | ``` 46 | 47 | ### TLS Support 48 | 49 | Enable TLS by providing a PEM file containing both certificate and private key: 50 | 51 | ```bash 52 | $ http-nu :3001 --tls cert.pem '{|req| "Secure Hello"}' 53 | $ curl -k https://localhost:3001 54 | Secure Hello 55 | ``` 56 | 57 | Generate a self-signed certificate for testing: 58 | 59 | ```bash 60 | $ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes 61 | $ cat cert.pem key.pem > combined.pem 62 | ``` 63 | 64 | ### Serving Static Files 65 | 66 | You can serve static files from a directory using the `.static` command. This 67 | command takes two arguments: the root directory path and the request path. 68 | 69 | When you call `.static`, it sets the response to serve the specified file, and 70 | any subsequent output in the closure will be ignored. The content type is 71 | automatically inferred based on the file extension (e.g., `text/css` for `.css` 72 | files). 73 | 74 | Here's an example: 75 | 76 | ```bash 77 | $ http-nu :3001 '{|req| .static "/path/to/static/dir" $req.path}' 78 | ``` 79 | 80 | ### POST: echo 81 | 82 | ```bash 83 | $ http-nu :3001 '{|req| $in}' 84 | $ curl -s -d Hai localhost:3001 85 | Hai 86 | ``` 87 | 88 | ### Request metadata 89 | 90 | The Request metadata is passed as an argument to the closure. 91 | 92 | ```bash 93 | $ http-nu :3001 '{|req| $req}' 94 | $ curl -s 'localhost:3001/segment?foo=bar&abc=123' # or 95 | $ http get 'http://localhost:3001/segment?foo=bar&abc=123' 96 | ─────────────┬─────────────────────────────── 97 | proto │ HTTP/1.1 98 | method │ GET 99 | uri │ /segment?foo=bar&abc=123 100 | path │ /segment 101 | remote_ip │ 127.0.0.1 102 | remote_port │ 52007 103 | │ ────────────┬──────────────── 104 | headers │ host │ localhost:3001 105 | │ user-agent │ curl/8.7.1 106 | │ accept │ */* 107 | │ ────────────┴──────────────── 108 | │ ─────┬───── 109 | query │ abc │ 123 110 | │ foo │ bar 111 | │ ─────┴───── 112 | ─────────────┴─────────────────────────────── 113 | 114 | $ http-nu :3001 '{|req| $"hello: ($req.path)"}' 115 | $ http get 'http://localhost:3001/yello' 116 | hello: /yello 117 | ``` 118 | 119 | ### Response metadata 120 | 121 | You can set the Response metadata using the `.response` custom command. 122 | 123 | ```nushell 124 | .response { 125 | status: # Optional, HTTP status code (default: 200) 126 | headers: { # Optional, HTTP headers 127 | : 128 | } 129 | } 130 | ``` 131 | 132 | ``` 133 | $ http-nu :3001 '{|req| .response {status: 404}; "sorry, eh"}' 134 | $ curl -si localhost:3001 135 | HTTP/1.1 404 Not Found 136 | transfer-encoding: chunked 137 | date: Fri, 31 Jan 2025 08:20:28 GMT 138 | 139 | sorry, eh 140 | ``` 141 | 142 | ### Content-Type Inference 143 | 144 | Content-type is determined in the following order of precedence: 145 | 146 | 1. Headers set via `.response` command: 147 | ```nushell 148 | .response { 149 | headers: { 150 | "Content-Type": "text/plain" 151 | } 152 | } 153 | ``` 154 | 155 | 2. Pipeline metadata content-type (e.g., from `to yaml`) 156 | 3. For Record values with no content-type, defaults to `application/json` 157 | 4. Otherwise defaults to `text/html; charset=utf-8` 158 | 159 | Examples: 160 | 161 | ```nushell 162 | # 1. Explicit header takes precedence 163 | {|req| .response {headers: {"Content-Type": "text/plain"}}; {foo: "bar"} } # Returns as text/plain 164 | 165 | # 2. Pipeline metadata 166 | {|req| ls | to yaml } # Returns as application/x-yaml 167 | 168 | # 3. Record auto-converts to JSON 169 | {|req| {foo: "bar"} } # Returns as application/json 170 | 171 | # 4. Default 172 | {|req| "Hello" } # Returns as text/html; charset=utf-8 173 | ``` 174 | 175 | ### Streaming responses 176 | 177 | Values returned by streaming pipelines (like `generate`) are sent to the client 178 | immediately as HTTP chunks. This allows real-time data transmission without 179 | waiting for the entire response to be ready. 180 | 181 | ```bash 182 | $ http-nu :3001 '{|req| 183 | .response {status: 200} 184 | generate {|_| 185 | sleep 1sec 186 | {out: (date now | to text | $in + "\n") next: true } 187 | } true 188 | }' 189 | $ curl -s localhost:3001 190 | Fri, 31 Jan 2025 03:47:59 -0500 (now) 191 | Fri, 31 Jan 2025 03:48:00 -0500 (now) 192 | Fri, 31 Jan 2025 03:48:01 -0500 (now) 193 | Fri, 31 Jan 2025 03:48:02 -0500 (now) 194 | Fri, 31 Jan 2025 03:48:03 -0500 (now) 195 | ... 196 | ``` 197 | 198 | ### [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) 199 | 200 | Use the `to sse` command to format records for the `text/event-stream` protocol. Each input record may contain the optional fields `data`, `id`, and `event` which will be emitted in the resulting stream. 201 | 202 | #### `to sse` 203 | 204 | Converts `{data? id? event?}` records into SSE strings. String values are used as-is while other values are serialized to compact JSON. Each event ends with an empty line. 205 | 206 | | input | output | 207 | | ----- | ------ | 208 | | record | string | 209 | 210 | Examples 211 | 212 | ```bash 213 | > {data: 'hello'} | to sse 214 | data: hello 215 | 216 | > {id: 1 event: greet data: 'hi'} | to sse 217 | id: 1 218 | event: greet 219 | data: hi 220 | 221 | > {data: "foo\nbar"} | to sse 222 | data: foo 223 | data: bar 224 | 225 | > {data: [1 2 3]} | to sse 226 | data: [1,2,3] 227 | ``` 228 | 229 | ```bash 230 | $ http-nu :3001 '{|req| 231 | .response {headers: {"content-type": "text/event-stream"}} 232 | tail -F source.json | lines | from json | to sse 233 | }' 234 | 235 | # simulate generating events in a seperate process 236 | $ loop { 237 | {date: (date now)} | to json -r | $in + "\n" | save -a source.json 238 | sleep 1sec 239 | } 240 | 241 | $ curl -si localhost:3001/ 242 | HTTP/1.1 200 OK 243 | content-type: text/event-stream 244 | transfer-encoding: chunked 245 | date: Fri, 31 Jan 2025 09:01:20 GMT 246 | 247 | data: {"date":"2025-01-31 04:01:23.371514 -05:00"} 248 | 249 | data: {"date":"2025-01-31 04:01:24.376864 -05:00"} 250 | 251 | data: {"date":"2025-01-31 04:01:25.382756 -05:00"} 252 | 253 | data: {"date":"2025-01-31 04:01:26.385418 -05:00"} 254 | 255 | data: {"date":"2025-01-31 04:01:27.387723 -05:00"} 256 | 257 | data: {"date":"2025-01-31 04:01:28.390407 -05:00"} 258 | ... 259 | ``` 260 | 261 | ## History 262 | 263 | If you prefer POSIX to [Nushell](https://www.nushell.sh), this project has a cousin called [http-sh](https://github.com/cablehead/http-sh). 264 | -------------------------------------------------------------------------------- /changes/v0.2.md: -------------------------------------------------------------------------------- 1 | # v0.2.0 2 | 3 | Added initial Windows support (Unix domain sockets are now properly gated) 4 | 5 | ## Raw commits 6 | 7 | * Update README.md (2025-01-31) 8 | * test: gate Unix socket tests for Windows compatibility (2025-01-31) 9 | * test: increase timing tolerance for CI environments (2025-01-31) 10 | * style: remove unnecessary return statement in Windows bind path (2025-01-31) 11 | * test: improve resilience of timing assertions with relative checks (2025-01-31) 12 | * fix: separate address parsing for Windows and Unix platforms (2025-01-31) 13 | * fix: gate unix socket imports for windows compatibility (2025-01-31) 14 | * test: improve duration assertion error messages (2025-01-31) 15 | * ci: replace deprecated actions with direct cargo commands (2025-01-31) 16 | * test: improve duration assertion error messages (2025-01-31) 17 | * ci: allow workflow to continue on platform-specific failures (2025-01-31) 18 | * ci: add cross-platform testing workflow (2025-01-31) 19 | * docs: README, fix port 🙏 @kiil (2025-01-31) 20 | -------------------------------------------------------------------------------- /changes/v0.3.0.md: -------------------------------------------------------------------------------- 1 | # v0.3.0 2 | 3 | ## Highlights 4 | 5 | - Content-Type is now inferred from the pipeline metadata 6 | - Flesh out support for ByteStream 7 | - nu_cmd_extra built-ins are now included (`to html` specifically) 8 | 9 | ## Raw commits 10 | 11 | * feat: support Nushell ByteStream output using blocking reader pattern (2025-02-03) 12 | * feat: improve content-type handling precedence and clarify documentation (2025-02-03) 13 | * docs: README (2025-02-02) 14 | * feat: attempt to infer content-type from the pipeline's metadata (#4) (2025-02-02) 15 | * feat: add nu_cmd_extra built-ins (2025-02-02) 16 | * chore: bump version to v0.2.0 and add changelog (2025-01-31) -------------------------------------------------------------------------------- /changes/v0.4.0.md: -------------------------------------------------------------------------------- 1 | # v0.4.0 2 | 3 | ## Highlights 4 | 5 | ### Serving Static Files 6 | 7 | You can serve static files from a directory using the `.static` command. This 8 | command takes two arguments: the root directory path and the request path. 9 | 10 | When you call `.static`, it sets the response to serve the specified file, and 11 | any subsequent output in the closure will be ignored. The content type is 12 | automatically inferred based on the file extension (e.g., `text/css` for `.css` 13 | files). 14 | 15 | Here's an example: 16 | 17 | ```bash 18 | $ http-nu :3001 '{|req| .static "/path/to/static/dir" $req.path}' 19 | ``` 20 | 21 | ### TLS Support 22 | 23 | Enable TLS by providing a PEM file containing both certificate and private key: 24 | 25 | ```bash 26 | $ http-nu :3001 --tls cert.pem '{|req| "Secure Hello"}' 27 | $ curl -k https://localhost:3001 28 | Secure Hello 29 | ``` 30 | 31 | ## Raw commits 32 | 33 | - feat: add some basic request logging (2025-02-20) 34 | - feat: add a .static built-in command to facilitate static file serving (#6) 35 | (2025-02-20) 36 | - fix: continue to serve if there's an error on accept (2025-02-13) 37 | - feat: add tls support (#5) (2025-02-13) 38 | - feat: log Nushell evaluation errors when processing a request (2025-02-13) 39 | - fix: capture the output from external commands (2025-02-06) 40 | - feat: move ResponseStartCommand to a thread_local pattern (2025-02-06) 41 | - feat: preserve the environment from executing the code snippet which returns 42 | the service closure ```nushell def do-foo [more: string] { "foo" + $more } 43 | (2025-02-05) 44 | - docs: README (2025-02-03) 45 | -------------------------------------------------------------------------------- /changes/v0.4.1.md: -------------------------------------------------------------------------------- 1 | cargo clippy -- -D warnings -------------------------------------------------------------------------------- /changes/v0.4.2.md: -------------------------------------------------------------------------------- 1 | feat: upgrade to nushell 0.103.0 2 | docs: add a basic example 3 | -------------------------------------------------------------------------------- /check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | cargo fmt --check 6 | cargo clippy -- -D warnings 7 | cargo test 8 | -------------------------------------------------------------------------------- /examples/basic.nu: -------------------------------------------------------------------------------- 1 | # basic.nu - A basic HTTP server example for http-nu 2 | # 3 | # Run with: cat examples/basic.nu | http-nu :3001 - 4 | 5 | {|req| 6 | match $req.path { 7 | # Home page 8 | "/" => { 9 | .response { headers: { "Content-Type": "text/html" } } 10 | " 11 |

http-nu demo

12 | 19 | " 20 | } 21 | 22 | # Hello world example 23 | "/hello" => { 24 | "Hello, World!" 25 | } 26 | 27 | # JSON response example 28 | "/json" => { 29 | { 30 | message: "This is JSON", 31 | timestamp: (date now | into int), 32 | server: "http-nu" 33 | } 34 | } 35 | 36 | # Echo POST data 37 | "/echo" => { 38 | if $req.method == "POST" { 39 | # Return the request body 40 | $in 41 | } else { 42 | .response { headers: { "Content-Type": "text/html" } } 43 | " 44 |

Echo Service

45 |

Send a POST request to this URL to echo the body.

46 |
47 | 48 |
49 | 50 |
51 | " 52 | } 53 | } 54 | 55 | # Time stream example 56 | "/time" => { 57 | .response { headers: { "Content-Type": "text/plain" } } 58 | generate {|_| 59 | sleep 1sec 60 | {out: $"Current time: (date now | format date '%Y-%m-%d %H:%M:%S')\n" next: true} 61 | } true 62 | } 63 | 64 | # Show request info 65 | "/info" => { 66 | $req 67 | } 68 | 69 | # 404 for everything else 70 | _ => { 71 | .response { status: 404 } 72 | "404 - Page not found" 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/engine.rs: -------------------------------------------------------------------------------- 1 | use nu_cli::{add_cli_context, gather_parent_env_vars}; 2 | use nu_cmd_lang::create_default_context; 3 | use nu_command::add_shell_command_context; 4 | use nu_engine::eval_block_with_early_return; 5 | use nu_parser::parse; 6 | use nu_protocol::engine::Command; 7 | use nu_protocol::format_shell_error; 8 | use nu_protocol::{ 9 | debugger::WithoutDebug, 10 | engine::{Closure, EngineState, Redirection, Stack, StateWorkingSet}, 11 | OutDest, PipelineData, ShellError, Span, Value, 12 | }; 13 | 14 | use crate::Error; 15 | 16 | #[derive(Clone)] 17 | pub struct Engine { 18 | pub state: EngineState, 19 | closure: Option, 20 | } 21 | 22 | impl Engine { 23 | pub fn new() -> Result { 24 | let mut engine_state = create_default_context(); 25 | 26 | engine_state = add_shell_command_context(engine_state); 27 | engine_state = add_cli_context(engine_state); 28 | engine_state = nu_cmd_extra::extra::add_extra_command_context(engine_state); 29 | 30 | let init_cwd = std::env::current_dir()?; 31 | gather_parent_env_vars(&mut engine_state, init_cwd.as_ref()); 32 | 33 | Ok(Self { 34 | state: engine_state, 35 | closure: None, 36 | }) 37 | } 38 | 39 | pub fn add_commands(&mut self, commands: Vec>) -> Result<(), Error> { 40 | let mut working_set = StateWorkingSet::new(&self.state); 41 | for command in commands { 42 | working_set.add_decl(command); 43 | } 44 | self.state.merge_delta(working_set.render())?; 45 | Ok(()) 46 | } 47 | 48 | pub fn parse_closure(&mut self, script: &str) -> Result<(), Error> { 49 | let mut working_set = StateWorkingSet::new(&self.state); 50 | let block = parse(&mut working_set, None, script.as_bytes(), false); 51 | 52 | // Handle parse errors 53 | if let Some(err) = working_set.parse_errors.first() { 54 | let shell_error = ShellError::GenericError { 55 | error: "Parse error".into(), 56 | msg: format!("{:?}", err), 57 | span: Some(err.span()), 58 | help: None, 59 | inner: vec![], 60 | }; 61 | return Err(Error::from(format_shell_error(&working_set, &shell_error))); 62 | } 63 | 64 | // Handle compile errors 65 | if let Some(err) = working_set.compile_errors.first() { 66 | let shell_error = ShellError::GenericError { 67 | error: format!("Compile error {}", err), 68 | msg: "".into(), 69 | span: None, 70 | help: None, 71 | inner: vec![], 72 | }; 73 | return Err(Error::from(format_shell_error(&working_set, &shell_error))); 74 | } 75 | 76 | self.state.merge_delta(working_set.render())?; 77 | 78 | let mut stack = Stack::new(); 79 | let result = eval_block_with_early_return::( 80 | &self.state, 81 | &mut stack, 82 | &block, 83 | PipelineData::empty(), 84 | ) 85 | .map_err(|err| { 86 | let working_set = StateWorkingSet::new(&self.state); 87 | Error::from(format_shell_error(&working_set, &err)) 88 | })?; 89 | 90 | let closure = result 91 | .into_value(Span::unknown()) 92 | .map_err(|err| { 93 | let working_set = StateWorkingSet::new(&self.state); 94 | Error::from(format_shell_error(&working_set, &err)) 95 | })? 96 | .into_closure() 97 | .map_err(|err| { 98 | let working_set = StateWorkingSet::new(&self.state); 99 | Error::from(format_shell_error(&working_set, &err)) 100 | })?; 101 | 102 | // Verify closure accepts exactly one argument 103 | let block = self.state.get_block(closure.block_id); 104 | if block.signature.required_positional.len() != 1 { 105 | return Err(format!( 106 | "Closure must accept exactly one request argument, found {}", 107 | block.signature.required_positional.len() 108 | ) 109 | .into()); 110 | } 111 | 112 | self.state.merge_env(&mut stack)?; 113 | 114 | self.closure = Some(closure); 115 | Ok(()) 116 | } 117 | 118 | pub fn eval(&self, input: Value, pipeline_data: PipelineData) -> Result { 119 | let closure = self.closure.as_ref().ok_or("Closure not parsed")?; 120 | 121 | let mut stack = Stack::new(); 122 | let mut stack = 123 | stack.push_redirection(Some(Redirection::Pipe(OutDest::PipeSeparate)), None); 124 | let block = self.state.get_block(closure.block_id); 125 | 126 | stack.add_var( 127 | block.signature.required_positional[0].var_id.unwrap(), 128 | input, 129 | ); 130 | 131 | eval_block_with_early_return::(&self.state, &mut stack, block, pipeline_data) 132 | .map_err(|err| { 133 | let working_set = StateWorkingSet::new(&self.state); 134 | Error::from(format_shell_error(&working_set, &err)) 135 | }) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/handler.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::collections::HashMap; 3 | use std::io::Read; 4 | use std::net::SocketAddr; 5 | use std::path::PathBuf; 6 | 7 | use serde::{Deserialize, Serialize}; 8 | 9 | use tokio::sync::mpsc; 10 | use tokio::sync::oneshot; 11 | use tokio_stream::wrappers::ReceiverStream; 12 | use tokio_stream::StreamExt; 13 | 14 | use http_body_util::{combinators::BoxBody, BodyExt, Empty, Full, StreamBody}; 15 | use hyper::body::{Bytes, Frame}; 16 | 17 | use nu_engine::command_prelude::Type; 18 | use nu_engine::CallExt; 19 | use nu_protocol::engine::{Call, Command, EngineState, Stack}; 20 | use nu_protocol::{ 21 | Category, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Value, 22 | }; 23 | 24 | #[derive(Clone, Debug, Serialize, Deserialize)] 25 | pub struct Request { 26 | pub proto: String, 27 | #[serde(with = "http_serde::method")] 28 | pub method: http::method::Method, 29 | #[serde(skip_serializing_if = "Option::is_none")] 30 | pub authority: Option, 31 | #[serde(skip_serializing_if = "Option::is_none")] 32 | pub remote_ip: Option, 33 | #[serde(skip_serializing_if = "Option::is_none")] 34 | pub remote_port: Option, 35 | #[serde(with = "http_serde::header_map")] 36 | pub headers: http::header::HeaderMap, 37 | #[serde(with = "http_serde::uri")] 38 | pub uri: http::Uri, 39 | pub path: String, 40 | pub query: HashMap, 41 | } 42 | 43 | #[derive(Clone, Debug)] 44 | pub struct Response { 45 | pub status: u16, 46 | pub headers: HashMap, 47 | pub body_type: ResponseBodyType, 48 | } 49 | 50 | #[derive(Clone, Debug)] 51 | pub enum ResponseBodyType { 52 | Normal, 53 | Static { root: PathBuf, path: String }, 54 | } 55 | 56 | type BoxError = Box; 57 | type HTTPResult = Result>, BoxError>; 58 | 59 | #[derive(Debug)] 60 | enum ResponseTransport { 61 | Empty, 62 | Full(Vec), 63 | Stream(mpsc::Receiver>), 64 | } 65 | 66 | pub async fn handle( 67 | engine: crate::Engine, 68 | addr: Option, 69 | req: hyper::Request, 70 | ) -> Result>, BoxError> 71 | where 72 | B: hyper::body::Body + Unpin + Send + 'static, 73 | B::Data: Into + Clone + Send, 74 | B::Error: Into + Send, 75 | { 76 | match handle_inner(engine, addr, req).await { 77 | Ok(response) => Ok(response), 78 | Err(err) => { 79 | eprintln!("Error handling request: {}", err); 80 | let response = hyper::Response::builder().status(500).body( 81 | Full::new("Internal Server Error".into()) 82 | .map_err(|never| match never {}) 83 | .boxed(), 84 | )?; 85 | Ok(response) 86 | } 87 | } 88 | } 89 | 90 | async fn handle_inner( 91 | engine: crate::Engine, 92 | addr: Option, 93 | req: hyper::Request, 94 | ) -> HTTPResult 95 | where 96 | B: hyper::body::Body + Unpin + Send + 'static, 97 | B::Data: Into + Clone + Send, 98 | B::Error: Into + Send, 99 | { 100 | let (parts, mut body) = req.into_parts(); 101 | 102 | // Create channels for request body streaming 103 | let (body_tx, mut body_rx) = tokio::sync::mpsc::channel::, BoxError>>(32); 104 | 105 | // Spawn task to read request body frames 106 | tokio::task::spawn(async move { 107 | while let Some(frame) = body.frame().await { 108 | match frame { 109 | Ok(frame) => { 110 | if let Some(data) = frame.data_ref() { 111 | let bytes: Bytes = (*data).clone().into(); 112 | if body_tx.send(Ok(bytes.to_vec())).await.is_err() { 113 | break; 114 | } 115 | } 116 | } 117 | Err(err) => { 118 | let _ = body_tx.send(Err(err.into())).await; 119 | break; 120 | } 121 | } 122 | } 123 | }); 124 | 125 | // Create ByteStream for Nu pipeline 126 | let stream = nu_protocol::ByteStream::from_fn( 127 | nu_protocol::Span::unknown(), 128 | engine.state.signals().clone(), 129 | nu_protocol::ByteStreamType::Unknown, 130 | move |buffer: &mut Vec| match body_rx.blocking_recv() { 131 | Some(Ok(bytes)) => { 132 | buffer.extend_from_slice(&bytes); 133 | Ok(true) 134 | } 135 | Some(Err(err)) => Err(nu_protocol::ShellError::GenericError { 136 | error: "Body read error".into(), 137 | msg: err.to_string(), 138 | span: None, 139 | help: None, 140 | inner: vec![], 141 | }), 142 | None => Ok(false), 143 | }, 144 | ); 145 | 146 | let request = Request { 147 | proto: format!("{:?}", parts.version), 148 | method: parts.method.clone(), 149 | authority: parts.uri.authority().map(|a| a.to_string()), 150 | remote_ip: addr.as_ref().map(|a| a.ip()), 151 | remote_port: addr.as_ref().map(|a| a.port()), 152 | headers: parts.headers.clone(), 153 | uri: parts.uri.clone(), 154 | path: parts.uri.path().to_string(), 155 | query: parts 156 | .uri 157 | .query() 158 | .map(|v| { 159 | url::form_urlencoded::parse(v.as_bytes()) 160 | .into_owned() 161 | .collect() 162 | }) 163 | .unwrap_or_else(HashMap::new), 164 | }; 165 | 166 | println!( 167 | "{}", 168 | serde_json::json!({"stamp": scru128::new(), "message": "request", "meta": request}) 169 | ); 170 | 171 | let (meta_rx, bridged_body) = spawn_eval_thread(engine, request, stream); 172 | 173 | // Wait for both: 174 | // 1. Metadata - either from .response or default values when closure skips .response 175 | // 2. Body pipeline to start (but not necessarily complete as it may stream) 176 | let (meta, body_result) = tokio::join!( 177 | async { 178 | meta_rx.await.unwrap_or(Response { 179 | status: 200, 180 | headers: HashMap::new(), 181 | body_type: ResponseBodyType::Normal, 182 | }) 183 | }, 184 | bridged_body 185 | ); 186 | 187 | match &meta.body_type { 188 | ResponseBodyType::Normal => build_normal_response(&meta, Ok(body_result?)).await, 189 | ResponseBodyType::Static { root, path } => { 190 | let resolver = hyper_staticfile::Resolver::new(root); 191 | let accept_encoding = parts 192 | .headers 193 | .get("accept-encoding") 194 | .map(hyper_staticfile::AcceptEncoding::from_header_value) 195 | .unwrap_or_else(hyper_staticfile::AcceptEncoding::none); 196 | let result = resolver.resolve_path(path, accept_encoding).await?; 197 | let response = hyper_staticfile::ResponseBuilder::new() 198 | .path(path) 199 | .request_parts(&parts.method, &parts.uri, &parts.headers) 200 | .build(result)?; 201 | let (parts, body) = response.into_parts(); 202 | let body = body 203 | .map_err(|e| Box::new(e) as Box) 204 | .boxed(); 205 | Ok(hyper::Response::from_parts(parts, body)) 206 | } 207 | } 208 | } 209 | 210 | async fn build_normal_response( 211 | meta: &Response, 212 | body_result: Result<(Option, ResponseTransport), BoxError>, 213 | ) -> HTTPResult { 214 | let (inferred_content_type, body) = body_result?; 215 | let mut builder = hyper::Response::builder().status(meta.status); 216 | let mut header_map = hyper::header::HeaderMap::new(); 217 | 218 | let content_type = meta 219 | .headers 220 | .get("content-type") 221 | .or(meta.headers.get("Content-Type")) 222 | .cloned() 223 | .or(inferred_content_type) 224 | .unwrap_or("text/html; charset=utf-8".to_string()); 225 | 226 | header_map.insert( 227 | hyper::header::CONTENT_TYPE, 228 | hyper::header::HeaderValue::from_str(&content_type)?, 229 | ); 230 | 231 | for (k, v) in &meta.headers { 232 | if k.to_lowercase() != "content-type" { 233 | header_map.insert( 234 | hyper::header::HeaderName::from_bytes(k.as_bytes())?, 235 | hyper::header::HeaderValue::from_str(v)?, 236 | ); 237 | } 238 | } 239 | 240 | *builder.headers_mut().unwrap() = header_map; 241 | 242 | let body = match body { 243 | ResponseTransport::Empty => Empty::::new() 244 | .map_err(|never| match never {}) 245 | .boxed(), 246 | ResponseTransport::Full(bytes) => Full::new(bytes.into()) 247 | .map_err(|never| match never {}) 248 | .boxed(), 249 | ResponseTransport::Stream(rx) => { 250 | let stream = ReceiverStream::new(rx).map(|data| Ok(Frame::data(Bytes::from(data)))); 251 | StreamBody::new(stream).boxed() 252 | } 253 | }; 254 | 255 | Ok(builder.body(body)?) 256 | } 257 | 258 | fn spawn_eval_thread( 259 | engine: crate::Engine, 260 | request: Request, 261 | stream: nu_protocol::ByteStream, 262 | ) -> ( 263 | oneshot::Receiver, 264 | oneshot::Receiver<(Option, ResponseTransport)>, 265 | ) { 266 | let (meta_tx, meta_rx) = tokio::sync::oneshot::channel(); 267 | let (body_tx, body_rx) = tokio::sync::oneshot::channel(); 268 | 269 | fn inner( 270 | engine: crate::Engine, 271 | request: Request, 272 | stream: nu_protocol::ByteStream, 273 | meta_tx: oneshot::Sender, 274 | body_tx: oneshot::Sender<(Option, ResponseTransport)>, 275 | ) -> Result<(), BoxError> { 276 | RESPONSE_TX.with(|tx| { 277 | *tx.borrow_mut() = Some(meta_tx); 278 | }); 279 | let result = engine.eval(request_to_value(&request, Span::unknown()), stream.into()); 280 | // Always clear the thread local storage after eval completes 281 | RESPONSE_TX.with(|tx| { 282 | let _ = tx.borrow_mut().take(); // This will drop the sender if it wasn't used 283 | }); 284 | let output = result?; 285 | let inferred_content_type = match &output { 286 | PipelineData::Value(Value::Record { .. }, meta) 287 | if meta.as_ref().and_then(|m| m.content_type.clone()).is_none() => 288 | { 289 | Some("application/json".to_string()) 290 | } 291 | PipelineData::Value(_, meta) | PipelineData::ListStream(_, meta) => { 292 | meta.as_ref().and_then(|m| m.content_type.clone()) 293 | } 294 | _ => None, 295 | }; 296 | match output { 297 | PipelineData::Empty => { 298 | let _ = body_tx.send((inferred_content_type, ResponseTransport::Empty)); 299 | Ok(()) 300 | } 301 | PipelineData::Value(Value::Nothing { .. }, _) => { 302 | let _ = body_tx.send((inferred_content_type, ResponseTransport::Empty)); 303 | Ok(()) 304 | } 305 | PipelineData::Value(value, _) => { 306 | let _ = body_tx.send(( 307 | inferred_content_type, 308 | ResponseTransport::Full(value_to_bytes(value)), 309 | )); 310 | Ok(()) 311 | } 312 | PipelineData::ListStream(stream, _) => { 313 | let (stream_tx, stream_rx) = tokio::sync::mpsc::channel(32); 314 | let _ = body_tx.send((inferred_content_type, ResponseTransport::Stream(stream_rx))); 315 | for value in stream.into_inner() { 316 | if stream_tx.blocking_send(value_to_bytes(value)).is_err() { 317 | break; 318 | } 319 | } 320 | Ok(()) 321 | } 322 | PipelineData::ByteStream(stream, meta) => { 323 | let (stream_tx, stream_rx) = tokio::sync::mpsc::channel(32); 324 | let _ = body_tx.send(( 325 | meta.as_ref().and_then(|m| m.content_type.clone()), 326 | ResponseTransport::Stream(stream_rx), 327 | )); 328 | let mut reader = stream 329 | .reader() 330 | .ok_or_else(|| "ByteStream has no reader".to_string())?; 331 | let mut buf = vec![0; 8192]; 332 | loop { 333 | match reader.read(&mut buf) { 334 | Ok(0) => break, // EOF 335 | Ok(n) => { 336 | if stream_tx.blocking_send(buf[..n].to_vec()).is_err() { 337 | break; 338 | } 339 | } 340 | Err(err) => return Err(err.into()), 341 | } 342 | } 343 | Ok(()) 344 | } 345 | } 346 | } 347 | 348 | std::thread::spawn(move || -> Result<(), std::convert::Infallible> { 349 | if let Err(e) = inner(engine, request, stream, meta_tx, body_tx) { 350 | eprintln!("Error in eval thread: {}", e); 351 | } 352 | Ok(()) 353 | }); 354 | 355 | (meta_rx, body_rx) 356 | } 357 | 358 | fn value_to_json(value: &Value) -> serde_json::Value { 359 | match value { 360 | Value::Nothing { .. } => serde_json::Value::Null, 361 | Value::Bool { val, .. } => serde_json::Value::Bool(*val), 362 | Value::Int { val, .. } => serde_json::Value::Number((*val).into()), 363 | Value::Float { val, .. } => serde_json::Number::from_f64(*val) 364 | .map(serde_json::Value::Number) 365 | .unwrap_or(serde_json::Value::Null), 366 | Value::String { val, .. } => serde_json::Value::String(val.clone()), 367 | Value::List { vals, .. } => { 368 | serde_json::Value::Array(vals.iter().map(value_to_json).collect()) 369 | } 370 | Value::Record { val, .. } => { 371 | let mut map = serde_json::Map::new(); 372 | for (k, v) in val.iter() { 373 | map.insert(k.clone(), value_to_json(v)); 374 | } 375 | serde_json::Value::Object(map) 376 | } 377 | _ => todo!(), 378 | } 379 | } 380 | 381 | fn value_to_bytes(value: Value) -> Vec { 382 | match value { 383 | Value::Nothing { .. } => Vec::new(), 384 | Value::String { val, .. } => val.into_bytes(), 385 | Value::Int { val, .. } => val.to_string().into_bytes(), 386 | Value::Float { val, .. } => val.to_string().into_bytes(), 387 | Value::Binary { val, .. } => val, 388 | Value::Bool { val, .. } => val.to_string().into_bytes(), 389 | 390 | // Both Lists and Records are encoded as JSON 391 | Value::List { .. } | Value::Record { .. } => serde_json::to_string(&value_to_json(&value)) 392 | .unwrap_or_else(|_| String::new()) 393 | .into_bytes(), 394 | 395 | _ => todo!("value_to_bytes: {:?}", value), 396 | } 397 | } 398 | 399 | #[derive(Clone)] 400 | pub struct ResponseStartCommand; 401 | 402 | impl Default for ResponseStartCommand { 403 | fn default() -> Self { 404 | Self::new() 405 | } 406 | } 407 | 408 | impl ResponseStartCommand { 409 | pub fn new() -> Self { 410 | Self 411 | } 412 | } 413 | 414 | impl Command for ResponseStartCommand { 415 | fn name(&self) -> &str { 416 | ".response" 417 | } 418 | 419 | fn description(&self) -> &str { 420 | "Start an HTTP response with status and headers" 421 | } 422 | 423 | fn signature(&self) -> Signature { 424 | Signature::build(".response") 425 | .required( 426 | "meta", 427 | SyntaxShape::Record(vec![]), // Add empty vec argument 428 | "response configuration with optional status and headers", 429 | ) 430 | .input_output_types(vec![(Type::Nothing, Type::Nothing)]) 431 | .category(Category::Custom("http".into())) 432 | } 433 | 434 | fn run( 435 | &self, 436 | engine_state: &EngineState, 437 | stack: &mut Stack, 438 | call: &Call, 439 | _input: PipelineData, 440 | ) -> Result { 441 | let meta: Value = call.req(engine_state, stack, 0)?; 442 | let record = meta.as_record()?; 443 | 444 | // Extract optional status, default to 200 445 | let status = match record.get("status") { 446 | Some(status_value) => status_value.as_int()? as u16, 447 | None => 200, 448 | }; 449 | 450 | // Extract headers 451 | let headers = match record.get("headers") { 452 | Some(headers_value) => { 453 | let headers_record = headers_value.as_record()?; 454 | let mut map = HashMap::new(); 455 | for (k, v) in headers_record.iter() { 456 | map.insert(k.clone(), v.as_str()?.to_string()); 457 | } 458 | map 459 | } 460 | None => HashMap::new(), 461 | }; 462 | 463 | // Create response and send through channel 464 | let response = Response { 465 | status, 466 | headers, 467 | body_type: ResponseBodyType::Normal, 468 | }; 469 | 470 | RESPONSE_TX.with(|tx| -> Result<_, ShellError> { 471 | if let Some(tx) = tx.borrow_mut().take() { 472 | tx.send(response).map_err(|_| ShellError::GenericError { 473 | error: "Failed to send response".into(), 474 | msg: "Channel closed".into(), 475 | span: Some(call.head), 476 | help: None, 477 | inner: vec![], 478 | })?; 479 | } 480 | Ok(()) 481 | })?; 482 | 483 | Ok(PipelineData::Empty) 484 | } 485 | } 486 | 487 | #[derive(Clone)] 488 | pub struct StaticCommand; 489 | 490 | impl Default for StaticCommand { 491 | fn default() -> Self { 492 | Self::new() 493 | } 494 | } 495 | 496 | impl StaticCommand { 497 | pub fn new() -> Self { 498 | Self 499 | } 500 | } 501 | 502 | impl Command for StaticCommand { 503 | fn name(&self) -> &str { 504 | ".static" 505 | } 506 | 507 | fn description(&self) -> &str { 508 | "Serve static files from a directory" 509 | } 510 | 511 | fn signature(&self) -> Signature { 512 | Signature::build(".static") 513 | .required("root", SyntaxShape::String, "root directory path") 514 | .required("path", SyntaxShape::String, "request path") 515 | .input_output_types(vec![(Type::Nothing, Type::Nothing)]) 516 | .category(Category::Custom("http".into())) 517 | } 518 | 519 | fn run( 520 | &self, 521 | engine_state: &EngineState, 522 | stack: &mut Stack, 523 | call: &Call, 524 | _input: PipelineData, 525 | ) -> Result { 526 | let root: String = call.req(engine_state, stack, 0)?; 527 | let path: String = call.req(engine_state, stack, 1)?; 528 | 529 | let response = Response { 530 | status: 200, 531 | headers: HashMap::new(), 532 | body_type: ResponseBodyType::Static { 533 | root: PathBuf::from(root), 534 | path, 535 | }, 536 | }; 537 | 538 | RESPONSE_TX.with(|tx| -> Result<_, ShellError> { 539 | if let Some(tx) = tx.borrow_mut().take() { 540 | tx.send(response).map_err(|_| ShellError::GenericError { 541 | error: "Failed to send response".into(), 542 | msg: "Channel closed".into(), 543 | span: Some(call.head), 544 | help: None, 545 | inner: vec![], 546 | })?; 547 | } 548 | Ok(()) 549 | })?; 550 | 551 | Ok(PipelineData::Empty) 552 | } 553 | } 554 | 555 | thread_local! { 556 | static RESPONSE_TX: RefCell>> = const { RefCell::new(None) }; 557 | } 558 | 559 | pub fn request_to_value(request: &Request, span: Span) -> Value { 560 | let mut record = Record::new(); 561 | 562 | record.push("proto", Value::string(request.proto.clone(), span)); 563 | record.push("method", Value::string(request.method.to_string(), span)); 564 | record.push("uri", Value::string(request.uri.to_string(), span)); 565 | record.push("path", Value::string(request.path.clone(), span)); 566 | 567 | if let Some(authority) = &request.authority { 568 | record.push("authority", Value::string(authority.clone(), span)); 569 | } 570 | 571 | if let Some(remote_ip) = &request.remote_ip { 572 | record.push("remote_ip", Value::string(remote_ip.to_string(), span)); 573 | } 574 | 575 | if let Some(remote_port) = &request.remote_port { 576 | record.push("remote_port", Value::int(*remote_port as i64, span)); 577 | } 578 | 579 | // Convert headers to a record 580 | let mut headers_record = Record::new(); 581 | for (key, value) in request.headers.iter() { 582 | headers_record.push( 583 | key.to_string(), 584 | Value::string(value.to_str().unwrap_or_default().to_string(), span), 585 | ); 586 | } 587 | record.push("headers", Value::record(headers_record, span)); 588 | 589 | // Convert query parameters to a record 590 | let mut query_record = Record::new(); 591 | for (key, value) in &request.query { 592 | query_record.push(key.clone(), Value::string(value.clone(), span)); 593 | } 594 | record.push("query", Value::record(query_record, span)); 595 | 596 | Value::record(record, span) 597 | } 598 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod engine; 2 | pub mod handler; 3 | pub mod listener; 4 | pub mod to_sse; 5 | 6 | pub use engine::Engine; 7 | pub use listener::Listener; 8 | pub use to_sse::ToSse; 9 | 10 | pub type Error = Box; 11 | 12 | #[cfg(test)] 13 | mod test_engine; 14 | #[cfg(test)] 15 | mod test_handler; 16 | -------------------------------------------------------------------------------- /src/listener.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Error, ErrorKind, Seek}; 2 | use std::path::PathBuf; 3 | use std::sync::Arc; 4 | 5 | use tokio::io::{AsyncRead, AsyncWrite}; 6 | use tokio::net::{TcpListener, TcpStream}; 7 | #[cfg(unix)] 8 | use tokio::net::{UnixListener, UnixStream}; 9 | use tokio_rustls::TlsAcceptor; 10 | 11 | pub trait AsyncReadWrite: AsyncRead + AsyncWrite {} 12 | 13 | impl AsyncReadWrite for T {} 14 | 15 | pub type AsyncReadWriteBox = Box; 16 | 17 | pub struct TlsConfig { 18 | acceptor: TlsAcceptor, 19 | } 20 | 21 | impl TlsConfig { 22 | pub fn from_pem(pem_path: PathBuf) -> io::Result { 23 | let pem = std::fs::File::open(&pem_path).map_err(|e| { 24 | Error::new( 25 | ErrorKind::NotFound, 26 | format!("Failed to open PEM file {}: {}", pem_path.display(), e), 27 | ) 28 | })?; 29 | let mut pem = std::io::BufReader::new(pem); 30 | 31 | let certs = rustls_pemfile::certs(&mut pem) 32 | .collect::, _>>() 33 | .map_err(|e| { 34 | Error::new( 35 | ErrorKind::InvalidData, 36 | format!("Invalid certificate: {}", e), 37 | ) 38 | })?; 39 | 40 | if certs.is_empty() { 41 | return Err(Error::new(ErrorKind::InvalidData, "No certificates found")); 42 | } 43 | 44 | pem.seek(std::io::SeekFrom::Start(0))?; 45 | 46 | let key = rustls_pemfile::private_key(&mut pem) 47 | .map_err(|e| { 48 | Error::new( 49 | ErrorKind::InvalidData, 50 | format!("Invalid private key: {}", e), 51 | ) 52 | })? 53 | .ok_or_else(|| Error::new(ErrorKind::InvalidData, "No private key found"))?; 54 | 55 | let config = rustls::ServerConfig::builder() 56 | .with_no_client_auth() 57 | .with_single_cert(certs, key) 58 | .map_err(|e| Error::new(ErrorKind::InvalidData, format!("TLS config error: {}", e)))?; 59 | 60 | Ok(Self { 61 | acceptor: TlsAcceptor::from(Arc::new(config)), 62 | }) 63 | } 64 | } 65 | 66 | pub enum Listener { 67 | Tcp { 68 | listener: TcpListener, 69 | tls_config: Option, 70 | }, 71 | #[cfg(unix)] 72 | Unix(UnixListener), 73 | } 74 | 75 | impl Listener { 76 | pub async fn accept( 77 | &mut self, 78 | ) -> io::Result<(AsyncReadWriteBox, Option)> { 79 | match self { 80 | Listener::Tcp { 81 | listener, 82 | tls_config, 83 | } => { 84 | let (stream, addr) = listener.accept().await?; 85 | 86 | let stream = if let Some(tls) = tls_config { 87 | // Handle TLS connection 88 | match tls.acceptor.accept(stream).await { 89 | Ok(tls_stream) => Box::new(tls_stream) as AsyncReadWriteBox, 90 | Err(e) => { 91 | return Err(io::Error::new( 92 | io::ErrorKind::ConnectionAborted, 93 | format!("TLS error: {}", e), 94 | )); 95 | } 96 | } 97 | } else { 98 | // Handle plain TCP connection 99 | Box::new(stream) 100 | }; 101 | 102 | Ok((stream, Some(addr))) 103 | } 104 | #[cfg(unix)] 105 | Listener::Unix(listener) => { 106 | let (stream, _) = listener.accept().await?; 107 | Ok((Box::new(stream), None)) 108 | } 109 | } 110 | } 111 | 112 | pub async fn bind(addr: &str, tls_config: Option) -> io::Result { 113 | #[cfg(windows)] 114 | { 115 | // On Windows, treat all addresses as TCP 116 | let mut addr = addr.to_owned(); 117 | if addr.starts_with(':') { 118 | addr = format!("127.0.0.1{}", addr); 119 | } 120 | let listener = TcpListener::bind(addr).await?; 121 | Ok(Listener::Tcp { 122 | listener, 123 | tls_config, 124 | }) 125 | } 126 | 127 | #[cfg(unix)] 128 | { 129 | if addr.starts_with('/') || addr.starts_with('.') { 130 | if tls_config.is_some() { 131 | return Err(io::Error::new( 132 | io::ErrorKind::InvalidInput, 133 | "TLS is not supported with Unix domain sockets", 134 | )); 135 | } 136 | let _ = std::fs::remove_file(addr); 137 | let listener = UnixListener::bind(addr)?; 138 | Ok(Listener::Unix(listener)) 139 | } else { 140 | let mut addr = addr.to_owned(); 141 | if addr.starts_with(':') { 142 | addr = format!("127.0.0.1{}", addr); 143 | } 144 | let listener = TcpListener::bind(addr).await?; 145 | Ok(Listener::Tcp { 146 | listener, 147 | tls_config, 148 | }) 149 | } 150 | } 151 | } 152 | 153 | #[allow(dead_code)] 154 | pub async fn connect(&self) -> io::Result { 155 | match self { 156 | Listener::Tcp { listener, .. } => { 157 | let stream = TcpStream::connect(listener.local_addr()?).await?; 158 | Ok(Box::new(stream)) 159 | } 160 | #[cfg(unix)] 161 | Listener::Unix(listener) => { 162 | let stream = 163 | UnixStream::connect(listener.local_addr()?.as_pathname().unwrap()).await?; 164 | Ok(Box::new(stream)) 165 | } 166 | } 167 | } 168 | } 169 | 170 | impl std::fmt::Display for Listener { 171 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 172 | match self { 173 | Listener::Tcp { 174 | listener, 175 | tls_config, 176 | } => { 177 | let addr = listener.local_addr().unwrap(); 178 | write!( 179 | f, 180 | "{}:{} {}", 181 | addr.ip(), 182 | addr.port(), 183 | if tls_config.is_some() { "(TLS)" } else { "" } 184 | ) 185 | } 186 | #[cfg(unix)] 187 | Listener::Unix(listener) => { 188 | let addr = listener.local_addr().unwrap(); 189 | let path = addr.as_pathname().unwrap(); 190 | write!(f, "{}", path.display()) 191 | } 192 | } 193 | } 194 | } 195 | 196 | #[cfg(test)] 197 | mod tests { 198 | use super::*; 199 | 200 | use tokio::io::AsyncReadExt; 201 | use tokio::io::AsyncWriteExt; 202 | 203 | async fn exercise_listener(addr: &str) { 204 | let mut listener = Listener::bind(addr, None).await.unwrap(); 205 | let mut client = listener.connect().await.unwrap(); 206 | 207 | let (mut serve, _) = listener.accept().await.unwrap(); 208 | let want = b"Hello from server!"; 209 | serve.write_all(want).await.unwrap(); 210 | drop(serve); 211 | 212 | let mut got = Vec::new(); 213 | client.read_to_end(&mut got).await.unwrap(); 214 | assert_eq!(want.to_vec(), got); 215 | } 216 | 217 | #[tokio::test] 218 | async fn test_bind_tcp() { 219 | exercise_listener(":0").await; 220 | } 221 | 222 | #[cfg(unix)] 223 | #[tokio::test] 224 | async fn test_bind_unix() { 225 | let temp_dir = tempfile::tempdir().unwrap(); 226 | let path = temp_dir.path().join("test.sock"); 227 | let path = path.to_str().unwrap(); 228 | exercise_listener(path).await; 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::Read; 2 | use std::path::PathBuf; 3 | 4 | use hyper::service::service_fn; 5 | use hyper_util::rt::TokioIo; 6 | 7 | use clap::Parser; 8 | 9 | use http_nu::{ 10 | handler::{handle, ResponseStartCommand, StaticCommand}, 11 | listener::TlsConfig, 12 | Engine, Listener, ToSse, 13 | }; 14 | 15 | #[derive(Parser, Debug)] 16 | #[clap(version)] 17 | struct Args { 18 | /// Address to listen on [HOST]:PORT or for Unix domain socket 19 | #[clap(value_parser)] 20 | addr: String, 21 | 22 | /// Path to PEM file containing certificate and private key 23 | #[clap(short, long)] 24 | tls: Option, 25 | 26 | /// Nushell closure to handle requests, or '-' to read from stdin 27 | #[clap(value_parser)] 28 | closure: String, 29 | } 30 | 31 | async fn serve(args: Args, engine: Engine) -> Result<(), Box> { 32 | // Configure TLS if enabled 33 | let tls_config = if let Some(pem_path) = args.tls { 34 | Some(TlsConfig::from_pem(pem_path)?) 35 | } else { 36 | None 37 | }; 38 | 39 | let mut listener = Listener::bind(&args.addr, tls_config).await?; 40 | println!( 41 | "{}", 42 | serde_json::json!({"stamp": scru128::new(), "message": "start", "address": format!("{}", listener)}) 43 | ); 44 | 45 | loop { 46 | match listener.accept().await { 47 | Ok((stream, remote_addr)) => { 48 | let io = TokioIo::new(stream); 49 | let engine = engine.clone(); 50 | 51 | tokio::task::spawn(async move { 52 | let service = service_fn(move |req| handle(engine.clone(), remote_addr, req)); 53 | if let Err(err) = hyper::server::conn::http1::Builder::new() 54 | .serve_connection(io, service) 55 | .await 56 | { 57 | eprintln!("Connection error: {}", err); 58 | } 59 | }); 60 | } 61 | Err(e) => { 62 | eprintln!("Error accepting connection: {}", e); 63 | continue; 64 | } 65 | } 66 | } 67 | } 68 | 69 | #[tokio::main] 70 | async fn main() -> Result<(), Box> { 71 | let args = Args::parse(); 72 | 73 | // Determine the closure source 74 | let closure_content = if args.closure == "-" { 75 | // Read closure from stdin 76 | let mut buffer = String::new(); 77 | std::io::stdin().read_to_string(&mut buffer)?; 78 | buffer 79 | } else { 80 | // Use the closure provided as argument 81 | args.closure.clone() 82 | }; 83 | 84 | let mut engine = Engine::new()?; 85 | engine.add_commands(vec![ 86 | Box::new(ResponseStartCommand::new()), 87 | Box::new(StaticCommand::new()), 88 | Box::new(ToSse {}), 89 | ])?; 90 | engine.parse_closure(&closure_content)?; 91 | 92 | serve(args, engine).await 93 | } 94 | -------------------------------------------------------------------------------- /src/test_engine.rs: -------------------------------------------------------------------------------- 1 | use nu_protocol::{PipelineData, Value}; 2 | 3 | use crate::Engine; 4 | 5 | #[test] 6 | fn test_engine_eval() { 7 | let mut engine = Engine::new().unwrap(); 8 | engine 9 | .parse_closure(r#"{|request| "hello world" }"#) 10 | .unwrap(); 11 | 12 | let test_value = Value::test_string("hello world"); 13 | let result = engine.eval(test_value, PipelineData::empty()).unwrap(); 14 | 15 | assert!(result 16 | .into_value(nu_protocol::Span::test_data()) 17 | .unwrap() 18 | .as_str() 19 | .unwrap() 20 | .contains("hello world")); 21 | } 22 | 23 | #[test] 24 | fn test_closure_no_args() { 25 | let mut engine = Engine::new().unwrap(); 26 | 27 | // Try to parse a closure with no arguments 28 | let result = engine.parse_closure(r#"{|| "hello world" }"#); 29 | 30 | // Assert the error contains the expected message 31 | assert!(result.is_err()); 32 | assert!(result 33 | .unwrap_err() 34 | .to_string() 35 | .contains("Closure must accept exactly one request argument, found 0")); 36 | } 37 | -------------------------------------------------------------------------------- /src/test_handler.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | use tokio::time::Duration; 4 | 5 | use http_body_util::BodyExt; 6 | use http_body_util::Empty; 7 | use http_body_util::Full; 8 | use hyper::body::Bytes; 9 | use hyper::Request; 10 | 11 | use crate::handler::handle; 12 | 13 | #[tokio::test] 14 | async fn test_handle() { 15 | let engine = test_engine(r#"{|req| "hello world" }"#); 16 | 17 | let req = Request::builder() 18 | .method("GET") 19 | .uri("/") 20 | .body(Empty::::new()) 21 | .unwrap(); 22 | 23 | let resp = handle(engine, None, req).await.unwrap(); 24 | assert_eq!(resp.status(), 200); 25 | 26 | let body = resp.into_body().collect().await.unwrap().to_bytes(); 27 | let body = String::from_utf8(body.to_vec()).unwrap(); 28 | assert!(body.contains("hello world")); 29 | } 30 | 31 | #[tokio::test] 32 | async fn test_handle_with_response_start() { 33 | let engine = test_engine( 34 | r#"{|req| 35 | match $req { 36 | {uri: "/resource" method: "POST"} => { 37 | .response { 38 | status: 201 39 | headers: { 40 | "Content-Type": "text/plain" 41 | "X-Custom": "test" 42 | } 43 | } 44 | "created resource" 45 | } 46 | } 47 | }"#, 48 | ); 49 | 50 | // Test successful POST to /resource 51 | let req = Request::builder() 52 | .method("POST") 53 | .uri("/resource") 54 | .body(Empty::::new()) 55 | .unwrap(); 56 | 57 | let resp = handle(engine.clone(), None, req).await.unwrap(); 58 | 59 | // Verify response metadata 60 | assert_eq!(resp.status(), 201); 61 | assert_eq!(resp.headers()["content-type"], "text/plain"); 62 | assert_eq!(resp.headers()["x-custom"], "test"); 63 | 64 | // Verify body 65 | let body = resp.into_body().collect().await.unwrap().to_bytes(); 66 | assert_eq!( 67 | String::from_utf8(body.to_vec()).unwrap(), 68 | "created resource" 69 | ); 70 | } 71 | 72 | #[tokio::test] 73 | async fn test_handle_post() { 74 | let engine = test_engine(r#"{|req| $in }"#); 75 | 76 | // Create POST request with a body 77 | let body = "Hello from the request body!"; 78 | let req = Request::builder() 79 | .method("POST") 80 | .uri("/echo") 81 | .body(Full::new(Bytes::from(body))) 82 | .unwrap(); 83 | 84 | let resp = handle(engine, None, req).await.unwrap(); 85 | 86 | // Verify response status 87 | assert_eq!(resp.status(), 200); 88 | 89 | // Verify body is echoed back 90 | let resp_body = resp.into_body().collect().await.unwrap().to_bytes(); 91 | assert_eq!(String::from_utf8(resp_body.to_vec()).unwrap(), body); 92 | } 93 | 94 | #[tokio::test] 95 | async fn test_handle_streaming() { 96 | let engine = test_engine( 97 | r#"{|req| 98 | 1..3 | each { |n| sleep 0.1sec; $n } 99 | }"#, 100 | ); 101 | 102 | let req = Request::builder() 103 | .method("GET") 104 | .uri("/stream") 105 | .body(Empty::::new()) 106 | .unwrap(); 107 | 108 | let resp = handle(engine, None, req).await.unwrap(); 109 | assert_eq!(resp.status(), 200); 110 | 111 | let mut body = resp.into_body(); 112 | let start_time = Instant::now(); 113 | let mut collected = Vec::new(); 114 | 115 | loop { 116 | match body.frame().await { 117 | Some(Ok(frame)) => { 118 | if let Some(data) = frame.data_ref() { 119 | let chunk_str = String::from_utf8(data.to_vec()).unwrap(); 120 | let elapsed = start_time.elapsed(); 121 | collected.push((chunk_str.trim().to_string(), elapsed)); 122 | } 123 | } 124 | Some(Err(e)) => panic!("Error reading frame: {}", e), 125 | None => break, 126 | } 127 | } 128 | 129 | // Should have 3 chunks 130 | assert_eq!(collected.len(), 3); 131 | assert_timing_sequence(&collected); 132 | } 133 | 134 | fn assert_timing_sequence(timings: &[(String, Duration)]) { 135 | // Check values arrive in sequence 136 | for i in 0..timings.len() { 137 | assert_eq!( 138 | timings[i].0, 139 | (i + 1).to_string(), 140 | "Values should arrive in sequence" 141 | ); 142 | } 143 | 144 | // Check each gap is roughly 100ms 145 | for i in 1..timings.len() { 146 | let gap = timings[i].1 - timings[i - 1].1; 147 | assert!( 148 | gap >= Duration::from_millis(50) && gap <= Duration::from_millis(300), 149 | "Gap between chunk {} and {} was {:?}, expected ~100ms", 150 | i, 151 | i + 1, 152 | gap 153 | ); 154 | } 155 | } 156 | 157 | #[tokio::test] 158 | async fn test_content_type_precedence() { 159 | // 1. Explicit header should take precedence 160 | let engine = test_engine( 161 | r#"{|req| 162 | .response {headers: {"Content-Type": "text/plain"}} 163 | {foo: "bar"} 164 | }"#, 165 | ); 166 | let req1 = Request::builder() 167 | .uri("/") 168 | .body(Empty::::new()) 169 | .unwrap(); 170 | let resp1 = handle(engine.clone(), None, req1).await.unwrap(); 171 | assert_eq!(resp1.headers()["content-type"], "text/plain"); 172 | 173 | // 2. Pipeline metadata 174 | let req2 = Request::builder() 175 | .uri("/") 176 | .body(Empty::::new()) 177 | .unwrap(); 178 | let engine = test_engine(r#"{|req| ls | to yaml }"#); 179 | let resp2 = handle(engine.clone(), None, req2).await.unwrap(); 180 | assert_eq!(resp2.headers()["content-type"], "application/yaml"); 181 | 182 | // 3. Record defaults to JSON 183 | let req3 = Request::builder() 184 | .uri("/") 185 | .body(Empty::::new()) 186 | .unwrap(); 187 | let engine = test_engine(r#"{|req| {foo: "bar"} }"#); 188 | let resp3 = handle(engine.clone(), None, req3).await.unwrap(); 189 | assert_eq!(resp3.headers()["content-type"], "application/json"); 190 | 191 | // 4. Plain text defaults to text/html 192 | let req4 = Request::builder() 193 | .uri("/") 194 | .body(Empty::::new()) 195 | .unwrap(); 196 | let engine = test_engine(r#"{|req| "Hello World"}"#); 197 | let resp4 = handle(engine.clone(), None, req4).await.unwrap(); 198 | assert_eq!(resp4.headers()["content-type"], "text/html; charset=utf-8"); 199 | } 200 | 201 | #[tokio::test] 202 | async fn test_handle_bytestream() { 203 | // `to csv` returns a ByteStream with content-type text/csv 204 | let engine = test_engine(r#"{|req| ls | to csv }"#); 205 | 206 | let req = Request::builder() 207 | .uri("/") 208 | .body(Empty::::new()) 209 | .unwrap(); 210 | 211 | let resp = handle(engine, None, req).await.unwrap(); 212 | 213 | // Verify CSV content type 214 | assert_eq!(resp.headers()["content-type"], "text/csv"); 215 | 216 | // Collect and verify body 217 | let body = resp.into_body().collect().await.unwrap().to_bytes(); 218 | let content = String::from_utf8(body.to_vec()).unwrap(); 219 | 220 | // Basic CSV format validation 221 | assert!(content.contains("name")); 222 | assert!(content.contains("type")); 223 | assert!(content.contains(",")); 224 | } 225 | 226 | #[tokio::test] 227 | async fn test_handle_preserve_preamble() { 228 | let engine = test_engine( 229 | r#" 230 | def do-foo [more: string] { 231 | "foo" + $more 232 | } 233 | 234 | {|req| 235 | do-foo $req.path 236 | } 237 | "#, 238 | ); 239 | 240 | let req = Request::builder() 241 | .uri("/bar") 242 | .body(Empty::::new()) 243 | .unwrap(); 244 | 245 | let resp = handle(engine, None, req).await.unwrap(); 246 | 247 | // Collect and verify body 248 | let body = resp.into_body().collect().await.unwrap().to_bytes(); 249 | let content = String::from_utf8(body.to_vec()).unwrap(); 250 | assert_eq!(content, "foo/bar"); 251 | } 252 | 253 | #[tokio::test] 254 | async fn test_handle_static() { 255 | let tmp = tempfile::tempdir().unwrap(); 256 | let static_dir = tmp.path().join("static"); 257 | std::fs::create_dir(&static_dir).unwrap(); 258 | 259 | let css = "body { background: blue; }"; 260 | std::fs::write(static_dir.join("styles.css"), css).unwrap(); 261 | 262 | let engine = test_engine(&format!( 263 | r#"{{|req| .static '{}' $req.path }}"#, 264 | static_dir.to_str().unwrap() 265 | )); 266 | 267 | let req = Request::builder() 268 | .uri("/styles.css") 269 | .body(Empty::::new()) 270 | .unwrap(); 271 | 272 | let resp = handle(engine, None, req).await.unwrap(); 273 | assert_eq!(resp.status(), 200); 274 | assert_eq!(resp.headers()["content-type"], "text/css"); 275 | 276 | let body = resp.into_body().collect().await.unwrap().to_bytes(); 277 | assert_eq!(String::from_utf8(body.to_vec()).unwrap(), css); 278 | } 279 | 280 | fn test_engine(script: &str) -> crate::Engine { 281 | let mut engine = crate::Engine::new().unwrap(); 282 | engine 283 | .add_commands(vec![ 284 | Box::new(super::handler::ResponseStartCommand::new()), 285 | Box::new(super::handler::StaticCommand::new()), 286 | Box::new(super::ToSse {}), 287 | ]) 288 | .unwrap(); 289 | engine.parse_closure(script).unwrap(); 290 | engine 291 | } 292 | 293 | #[tokio::test] 294 | async fn test_handle_binary_value() { 295 | // Test data: simple binary content (PNG-like header and some bytes) 296 | let expected_binary = vec![ 297 | 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, // PNG signature 298 | 0xFF, 0xAA, 0xBB, 0xCC, 0xDD, // Additional bytes 299 | ]; 300 | 301 | // Create engine that returns a binary value directly 302 | let engine = test_engine( 303 | r#"{|req| 304 | .response { 305 | headers: {"Content-Type": "application/octet-stream"} 306 | } 307 | 0x[89 50 4E 47 0D 0A 1A 0A FF AA BB CC DD] # Creates a Binary value type 308 | }"#, 309 | ); 310 | 311 | let req = Request::builder() 312 | .uri("/binary-value") 313 | .body(Empty::::new()) 314 | .unwrap(); 315 | 316 | // Currently this will panic, but after fixing it should return a response 317 | let resp = handle(engine, None, req).await.unwrap(); 318 | 319 | // Assert proper content type 320 | assert_eq!(resp.status(), 200); 321 | assert_eq!(resp.headers()["content-type"], "application/octet-stream"); 322 | 323 | // Assert binary content matches exactly 324 | let body = resp.into_body().collect().await.unwrap().to_bytes(); 325 | assert_eq!(body.to_vec(), expected_binary); 326 | } 327 | -------------------------------------------------------------------------------- /src/to_sse.rs: -------------------------------------------------------------------------------- 1 | use nu_engine::command_prelude::*; 2 | use nu_protocol::{ByteStream, ByteStreamType, Config, PipelineMetadata, Span, Value}; 3 | use serde_json; 4 | 5 | const LINE_ENDING: &str = "\n"; 6 | 7 | #[derive(Clone)] 8 | pub struct ToSse; 9 | 10 | impl Command for ToSse { 11 | fn name(&self) -> &str { 12 | "to sse" 13 | } 14 | 15 | fn signature(&self) -> Signature { 16 | Signature::build("to sse") 17 | .input_output_types(vec![(Type::record(), Type::String)]) 18 | .category(Category::Formats) 19 | } 20 | 21 | fn description(&self) -> &str { 22 | "Convert records into text/event-stream format" 23 | } 24 | 25 | fn search_terms(&self) -> Vec<&str> { 26 | vec!["sse", "server", "event"] 27 | } 28 | 29 | fn examples(&self) -> Vec { 30 | vec![Example { 31 | description: "Convert a record into a server-sent event", 32 | example: "{data: 'hello'} | to sse", 33 | result: Some(Value::test_string("data: hello\n\n")), 34 | }] 35 | } 36 | 37 | fn run( 38 | &self, 39 | engine_state: &EngineState, 40 | stack: &mut Stack, 41 | call: &Call, 42 | input: PipelineData, 43 | ) -> Result { 44 | let head = call.head; 45 | let config = stack.get_config(engine_state); 46 | match input { 47 | PipelineData::ListStream(stream, meta) => { 48 | let span = stream.span(); 49 | let cfg = config.clone(); 50 | let iter = stream 51 | .into_iter() 52 | .map(move |val| event_to_string(&cfg, val)); 53 | let stream = ByteStream::from_result_iter( 54 | iter, 55 | span, 56 | engine_state.signals().clone(), 57 | ByteStreamType::String, 58 | ); 59 | Ok(PipelineData::ByteStream(stream, update_metadata(meta))) 60 | } 61 | PipelineData::Value(Value::List { vals, .. }, meta) => { 62 | let cfg = config.clone(); 63 | let iter = vals.into_iter().map(move |val| event_to_string(&cfg, val)); 64 | let span = head; 65 | let stream = ByteStream::from_result_iter( 66 | iter, 67 | span, 68 | engine_state.signals().clone(), 69 | ByteStreamType::String, 70 | ); 71 | Ok(PipelineData::ByteStream(stream, update_metadata(meta))) 72 | } 73 | PipelineData::Value(val, meta) => { 74 | let out = event_to_string(&config, val)?; 75 | Ok( 76 | Value::string(out, head) 77 | .into_pipeline_data_with_metadata(update_metadata(meta)), 78 | ) 79 | } 80 | PipelineData::Empty => Ok(PipelineData::Value( 81 | Value::string(String::new(), head), 82 | update_metadata(None), 83 | )), 84 | PipelineData::ByteStream(..) => Err(ShellError::TypeMismatch { 85 | err_message: "expected record input".into(), 86 | span: head, 87 | }), 88 | } 89 | } 90 | } 91 | 92 | #[allow(clippy::result_large_err)] 93 | fn event_to_string(config: &Config, val: Value) -> Result { 94 | let span = val.span(); 95 | let rec = match val { 96 | Value::Record { val, .. } => val, 97 | other => { 98 | return Err(ShellError::TypeMismatch { 99 | err_message: format!("expected record, got {}", other.get_type()), 100 | span, 101 | }) 102 | } 103 | }; 104 | let mut out = String::new(); 105 | if let Some(id) = rec.get("id") { 106 | out.push_str("id: "); 107 | out.push_str(&id.to_expanded_string("", config)); 108 | out.push_str(LINE_ENDING); 109 | } 110 | if let Some(event) = rec.get("event") { 111 | out.push_str("event: "); 112 | out.push_str(&event.to_expanded_string("", config)); 113 | out.push_str(LINE_ENDING); 114 | } 115 | if let Some(data) = rec.get("data") { 116 | let data_str = match data { 117 | Value::String { val, .. } => val.clone(), 118 | _ => { 119 | let json_value = 120 | value_to_json(data, config).map_err(|err| ShellError::GenericError { 121 | error: err.to_string(), 122 | msg: "failed to serialize json".into(), 123 | span: Some(Span::unknown()), 124 | help: None, 125 | inner: vec![], 126 | })?; 127 | serde_json::to_string(&json_value).map_err(|err| ShellError::GenericError { 128 | error: err.to_string(), 129 | msg: "failed to serialize json".into(), 130 | span: Some(Span::unknown()), 131 | help: None, 132 | inner: vec![], 133 | })? 134 | } 135 | }; 136 | for line in data_str.lines() { 137 | out.push_str("data: "); 138 | out.push_str(line); 139 | out.push_str(LINE_ENDING); 140 | } 141 | } 142 | out.push_str(LINE_ENDING); 143 | Ok(out) 144 | } 145 | 146 | fn value_to_json(val: &Value, config: &Config) -> serde_json::Result { 147 | Ok(match val { 148 | Value::Bool { val, .. } => serde_json::Value::Bool(*val), 149 | Value::Int { val, .. } => serde_json::Value::from(*val), 150 | Value::Float { val, .. } => serde_json::Number::from_f64(*val) 151 | .map(serde_json::Value::Number) 152 | .unwrap_or(serde_json::Value::Null), 153 | Value::String { val, .. } => serde_json::Value::String(val.clone()), 154 | Value::List { vals, .. } => serde_json::Value::Array( 155 | vals.iter() 156 | .map(|v| value_to_json(v, config)) 157 | .collect::, _>>()?, 158 | ), 159 | Value::Record { val, .. } => { 160 | let mut map = serde_json::Map::new(); 161 | for (k, v) in val.iter() { 162 | map.insert(k.clone(), value_to_json(v, config)?); 163 | } 164 | serde_json::Value::Object(map) 165 | } 166 | Value::Nothing { .. } => serde_json::Value::Null, 167 | other => serde_json::Value::String(other.to_expanded_string("", config)), 168 | }) 169 | } 170 | 171 | fn update_metadata(metadata: Option) -> Option { 172 | metadata 173 | .map(|md| md.with_content_type(Some("text/event-stream".into()))) 174 | .or_else(|| { 175 | Some(PipelineMetadata::default().with_content_type(Some("text/event-stream".into()))) 176 | }) 177 | } 178 | 179 | #[cfg(test)] 180 | mod test { 181 | use super::*; 182 | 183 | #[test] 184 | fn test_content_type_metadata() { 185 | use nu_cmd_lang::eval_pipeline_without_terminal_expression; 186 | use nu_command::{Get, Metadata}; 187 | let mut engine_state = Box::new(EngineState::new()); 188 | let delta = { 189 | let mut working_set = StateWorkingSet::new(&engine_state); 190 | working_set.add_decl(Box::new(ToSse {})); 191 | working_set.add_decl(Box::new(Metadata {})); 192 | working_set.add_decl(Box::new(Get {})); 193 | working_set.render() 194 | }; 195 | engine_state.merge_delta(delta).expect("merge"); 196 | let cmd = "{data: 'x'} | to sse | metadata | get content_type"; 197 | let result = eval_pipeline_without_terminal_expression( 198 | cmd, 199 | std::env::temp_dir().as_ref(), 200 | &mut engine_state, 201 | ); 202 | assert_eq!( 203 | Value::test_record(record!("content_type" => Value::test_string("text/event-stream"))), 204 | result.expect("result") 205 | ); 206 | } 207 | 208 | #[test] 209 | fn test_full_event_output() { 210 | let record = record! { 211 | "id" => Value::test_string("42"), 212 | "event" => Value::test_string("greeting"), 213 | "data" => Value::test_string("Hello\nWorld"), 214 | }; 215 | let val = Value::record(record, Span::unknown()); 216 | let out = event_to_string(&Config::default(), val).unwrap(); 217 | let expected = "id: 42\nevent: greeting\ndata: Hello\ndata: World\n\n"; 218 | assert_eq!(out, expected); 219 | } 220 | 221 | #[test] 222 | fn test_non_record_error() { 223 | let err = event_to_string(&Config::default(), Value::test_int(123)).unwrap_err(); 224 | match err { 225 | ShellError::TypeMismatch { err_message, span } => { 226 | assert_eq!(span, Span::test_data()); 227 | assert!(err_message.contains("expected record")); 228 | } 229 | other => panic!("unexpected error: {:?}", other), 230 | } 231 | } 232 | } 233 | --------------------------------------------------------------------------------