├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ └── test.yml ├── .gitignore ├── .yarnrc.yml ├── Cargo.lock ├── Cargo.toml ├── LICENSE_APACHE ├── LICENSE_MIT ├── README.md ├── example ├── Cargo.lock ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── package.json ├── scripts └── build.sh ├── src ├── arrow_js │ ├── data.rs │ ├── enum.rs │ ├── field.rs │ ├── mod.rs │ ├── record_batch.rs │ ├── schema.rs │ ├── table.rs │ └── type.rs ├── data.rs ├── datatype.rs ├── error.rs ├── ffi │ ├── chunked.rs │ ├── data.rs │ ├── mod.rs │ ├── schema.rs │ └── stream.rs ├── field.rs ├── lib.rs ├── record_batch.rs ├── schema.rs ├── table.rs ├── utils.rs └── vector.rs ├── tsconfig.docs.json ├── typedoc.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.{js,json,yml}] 8 | charset = utf-8 9 | indent_style = space 10 | indent_size = 2 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | groups: 9 | arrow-rs: 10 | patterns: 11 | - "arrow*" 12 | exclude-patterns: 13 | - "arrow2*" 14 | arrow2: 15 | patterns: 16 | - "arrow2" 17 | other: 18 | patterns: 19 | - "*" 20 | exclude-patterns: 21 | - "arrow*" 22 | - package-ecosystem: github-actions 23 | directory: "/" 24 | schedule: 25 | interval: weekly 26 | open-pull-requests-limit: 10 27 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | lint-test: 11 | name: Lint and Test 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Install Rust 17 | uses: dtolnay/rust-toolchain@stable 18 | with: 19 | components: rustfmt, clippy 20 | 21 | - uses: Swatinem/rust-cache@v2 22 | 23 | - name: Cargo fmt 24 | run: cargo fmt --all -- --check 25 | 26 | - name: "clippy" 27 | run: cargo clippy --all --tests -- -D warnings 28 | 29 | - name: "test" 30 | run: | 31 | cargo test --all 32 | 33 | check: 34 | runs-on: ubuntu-latest 35 | steps: 36 | - uses: actions/checkout@v4 37 | 38 | - name: Install Rust 39 | uses: dtolnay/rust-toolchain@stable 40 | with: 41 | targets: wasm32-unknown-unknown 42 | 43 | - uses: Swatinem/rust-cache@v2 44 | 45 | - run: cargo install cargo-all-features 46 | 47 | - name: Check all combinations of features can build 48 | run: cargo check-all-features --target wasm32-unknown-unknown 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | 4 | docs_build 5 | .yarn 6 | .pnp.cjs 7 | .pnp.loader.mjs 8 | 9 | # Generated by Cargo 10 | # will have compiled files and executables 11 | debug/ 12 | target/ 13 | 14 | # These are backup files generated by rustfmt 15 | **/*.rs.bk 16 | 17 | # MSVC Windows builds of rustc generate these, which store debugging information 18 | *.pdb 19 | pkg/ 20 | 21 | node_modules 22 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ahash" 7 | version = "0.8.11" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 10 | dependencies = [ 11 | "cfg-if", 12 | "const-random", 13 | "getrandom", 14 | "once_cell", 15 | "version_check", 16 | "zerocopy", 17 | ] 18 | 19 | [[package]] 20 | name = "android-tzdata" 21 | version = "0.1.1" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 24 | 25 | [[package]] 26 | name = "android_system_properties" 27 | version = "0.1.5" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 30 | dependencies = [ 31 | "libc", 32 | ] 33 | 34 | [[package]] 35 | name = "arrow-array" 36 | version = "55.0.0" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "cebfe926794fbc1f49ddd0cdaf898956ca9f6e79541efce62dabccfd81380472" 39 | dependencies = [ 40 | "ahash", 41 | "arrow-buffer", 42 | "arrow-data", 43 | "arrow-schema", 44 | "chrono", 45 | "half", 46 | "hashbrown", 47 | "num", 48 | ] 49 | 50 | [[package]] 51 | name = "arrow-buffer" 52 | version = "55.0.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "0303c7ec4cf1a2c60310fc4d6bbc3350cd051a17bf9e9c0a8e47b4db79277824" 55 | dependencies = [ 56 | "bytes", 57 | "half", 58 | "num", 59 | ] 60 | 61 | [[package]] 62 | name = "arrow-data" 63 | version = "55.0.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "e8affacf3351a24039ea24adab06f316ded523b6f8c3dbe28fbac5f18743451b" 66 | dependencies = [ 67 | "arrow-buffer", 68 | "arrow-schema", 69 | "half", 70 | "num", 71 | ] 72 | 73 | [[package]] 74 | name = "arrow-ipc" 75 | version = "55.0.0" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "69880a9e6934d9cba2b8630dd08a3463a91db8693b16b499d54026b6137af284" 78 | dependencies = [ 79 | "arrow-array", 80 | "arrow-buffer", 81 | "arrow-data", 82 | "arrow-schema", 83 | "flatbuffers", 84 | ] 85 | 86 | [[package]] 87 | name = "arrow-schema" 88 | version = "55.0.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "7450c76ab7c5a6805be3440dc2e2096010da58f7cab301fdc996a4ee3ee74e49" 91 | dependencies = [ 92 | "bitflags", 93 | ] 94 | 95 | [[package]] 96 | name = "arrow-wasm" 97 | version = "0.1.0" 98 | dependencies = [ 99 | "arrow-array", 100 | "arrow-buffer", 101 | "arrow-data", 102 | "arrow-ipc", 103 | "arrow-schema", 104 | "console_error_panic_hook", 105 | "getrandom", 106 | "js-sys", 107 | "serde", 108 | "serde-wasm-bindgen", 109 | "thiserror", 110 | "wasm-bindgen", 111 | "wasm-bindgen-test", 112 | ] 113 | 114 | [[package]] 115 | name = "autocfg" 116 | version = "1.4.0" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 119 | 120 | [[package]] 121 | name = "bitflags" 122 | version = "2.9.0" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 125 | 126 | [[package]] 127 | name = "bumpalo" 128 | version = "3.16.0" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 131 | 132 | [[package]] 133 | name = "bytes" 134 | version = "1.10.1" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 137 | 138 | [[package]] 139 | name = "cc" 140 | version = "1.1.16" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" 143 | dependencies = [ 144 | "shlex", 145 | ] 146 | 147 | [[package]] 148 | name = "cfg-if" 149 | version = "1.0.0" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 152 | 153 | [[package]] 154 | name = "chrono" 155 | version = "0.4.40" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" 158 | dependencies = [ 159 | "android-tzdata", 160 | "iana-time-zone", 161 | "num-traits", 162 | "windows-link", 163 | ] 164 | 165 | [[package]] 166 | name = "console_error_panic_hook" 167 | version = "0.1.7" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 170 | dependencies = [ 171 | "cfg-if", 172 | "wasm-bindgen", 173 | ] 174 | 175 | [[package]] 176 | name = "const-random" 177 | version = "0.1.18" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" 180 | dependencies = [ 181 | "const-random-macro", 182 | ] 183 | 184 | [[package]] 185 | name = "const-random-macro" 186 | version = "0.1.16" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 189 | dependencies = [ 190 | "getrandom", 191 | "once_cell", 192 | "tiny-keccak", 193 | ] 194 | 195 | [[package]] 196 | name = "core-foundation-sys" 197 | version = "0.8.7" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 200 | 201 | [[package]] 202 | name = "crunchy" 203 | version = "0.2.3" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" 206 | 207 | [[package]] 208 | name = "flatbuffers" 209 | version = "25.2.10" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "1045398c1bfd89168b5fd3f1fc11f6e70b34f6f66300c87d44d3de849463abf1" 212 | dependencies = [ 213 | "bitflags", 214 | "rustc_version", 215 | ] 216 | 217 | [[package]] 218 | name = "getrandom" 219 | version = "0.2.15" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 222 | dependencies = [ 223 | "cfg-if", 224 | "js-sys", 225 | "libc", 226 | "wasi", 227 | "wasm-bindgen", 228 | ] 229 | 230 | [[package]] 231 | name = "half" 232 | version = "2.6.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" 235 | dependencies = [ 236 | "cfg-if", 237 | "crunchy", 238 | "num-traits", 239 | ] 240 | 241 | [[package]] 242 | name = "hashbrown" 243 | version = "0.15.2" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 246 | 247 | [[package]] 248 | name = "iana-time-zone" 249 | version = "0.1.63" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" 252 | dependencies = [ 253 | "android_system_properties", 254 | "core-foundation-sys", 255 | "iana-time-zone-haiku", 256 | "js-sys", 257 | "log", 258 | "wasm-bindgen", 259 | "windows-core", 260 | ] 261 | 262 | [[package]] 263 | name = "iana-time-zone-haiku" 264 | version = "0.1.2" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 267 | dependencies = [ 268 | "cc", 269 | ] 270 | 271 | [[package]] 272 | name = "itoa" 273 | version = "1.0.11" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 276 | 277 | [[package]] 278 | name = "js-sys" 279 | version = "0.3.77" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 282 | dependencies = [ 283 | "once_cell", 284 | "wasm-bindgen", 285 | ] 286 | 287 | [[package]] 288 | name = "libc" 289 | version = "0.2.158" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" 292 | 293 | [[package]] 294 | name = "libm" 295 | version = "0.2.11" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" 298 | 299 | [[package]] 300 | name = "log" 301 | version = "0.4.22" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 304 | 305 | [[package]] 306 | name = "memchr" 307 | version = "2.7.4" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 310 | 311 | [[package]] 312 | name = "minicov" 313 | version = "0.3.5" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169" 316 | dependencies = [ 317 | "cc", 318 | "walkdir", 319 | ] 320 | 321 | [[package]] 322 | name = "num" 323 | version = "0.4.3" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" 326 | dependencies = [ 327 | "num-bigint", 328 | "num-complex", 329 | "num-integer", 330 | "num-iter", 331 | "num-rational", 332 | "num-traits", 333 | ] 334 | 335 | [[package]] 336 | name = "num-bigint" 337 | version = "0.4.6" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 340 | dependencies = [ 341 | "num-integer", 342 | "num-traits", 343 | ] 344 | 345 | [[package]] 346 | name = "num-complex" 347 | version = "0.4.6" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 350 | dependencies = [ 351 | "num-traits", 352 | ] 353 | 354 | [[package]] 355 | name = "num-integer" 356 | version = "0.1.46" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 359 | dependencies = [ 360 | "num-traits", 361 | ] 362 | 363 | [[package]] 364 | name = "num-iter" 365 | version = "0.1.45" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 368 | dependencies = [ 369 | "autocfg", 370 | "num-integer", 371 | "num-traits", 372 | ] 373 | 374 | [[package]] 375 | name = "num-rational" 376 | version = "0.4.2" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 379 | dependencies = [ 380 | "num-bigint", 381 | "num-integer", 382 | "num-traits", 383 | ] 384 | 385 | [[package]] 386 | name = "num-traits" 387 | version = "0.2.19" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 390 | dependencies = [ 391 | "autocfg", 392 | "libm", 393 | ] 394 | 395 | [[package]] 396 | name = "once_cell" 397 | version = "1.19.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 400 | 401 | [[package]] 402 | name = "proc-macro2" 403 | version = "1.0.86" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 406 | dependencies = [ 407 | "unicode-ident", 408 | ] 409 | 410 | [[package]] 411 | name = "quote" 412 | version = "1.0.37" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 415 | dependencies = [ 416 | "proc-macro2", 417 | ] 418 | 419 | [[package]] 420 | name = "rustc_version" 421 | version = "0.4.1" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 424 | dependencies = [ 425 | "semver", 426 | ] 427 | 428 | [[package]] 429 | name = "rustversion" 430 | version = "1.0.19" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 433 | 434 | [[package]] 435 | name = "ryu" 436 | version = "1.0.18" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 439 | 440 | [[package]] 441 | name = "same-file" 442 | version = "1.0.6" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 445 | dependencies = [ 446 | "winapi-util", 447 | ] 448 | 449 | [[package]] 450 | name = "semver" 451 | version = "1.0.26" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 454 | 455 | [[package]] 456 | name = "serde" 457 | version = "1.0.219" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 460 | dependencies = [ 461 | "serde_derive", 462 | ] 463 | 464 | [[package]] 465 | name = "serde-wasm-bindgen" 466 | version = "0.6.5" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" 469 | dependencies = [ 470 | "js-sys", 471 | "serde", 472 | "wasm-bindgen", 473 | ] 474 | 475 | [[package]] 476 | name = "serde_derive" 477 | version = "1.0.219" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 480 | dependencies = [ 481 | "proc-macro2", 482 | "quote", 483 | "syn", 484 | ] 485 | 486 | [[package]] 487 | name = "serde_json" 488 | version = "1.0.127" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" 491 | dependencies = [ 492 | "itoa", 493 | "memchr", 494 | "ryu", 495 | "serde", 496 | ] 497 | 498 | [[package]] 499 | name = "shlex" 500 | version = "1.3.0" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 503 | 504 | [[package]] 505 | name = "syn" 506 | version = "2.0.87" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" 509 | dependencies = [ 510 | "proc-macro2", 511 | "quote", 512 | "unicode-ident", 513 | ] 514 | 515 | [[package]] 516 | name = "thiserror" 517 | version = "2.0.12" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 520 | dependencies = [ 521 | "thiserror-impl", 522 | ] 523 | 524 | [[package]] 525 | name = "thiserror-impl" 526 | version = "2.0.12" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 529 | dependencies = [ 530 | "proc-macro2", 531 | "quote", 532 | "syn", 533 | ] 534 | 535 | [[package]] 536 | name = "tiny-keccak" 537 | version = "2.0.2" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 540 | dependencies = [ 541 | "crunchy", 542 | ] 543 | 544 | [[package]] 545 | name = "unicode-ident" 546 | version = "1.0.12" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 549 | 550 | [[package]] 551 | name = "version_check" 552 | version = "0.9.5" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 555 | 556 | [[package]] 557 | name = "walkdir" 558 | version = "2.5.0" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 561 | dependencies = [ 562 | "same-file", 563 | "winapi-util", 564 | ] 565 | 566 | [[package]] 567 | name = "wasi" 568 | version = "0.11.0+wasi-snapshot-preview1" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 571 | 572 | [[package]] 573 | name = "wasm-bindgen" 574 | version = "0.2.100" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 577 | dependencies = [ 578 | "cfg-if", 579 | "once_cell", 580 | "rustversion", 581 | "serde", 582 | "serde_json", 583 | "wasm-bindgen-macro", 584 | ] 585 | 586 | [[package]] 587 | name = "wasm-bindgen-backend" 588 | version = "0.2.100" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 591 | dependencies = [ 592 | "bumpalo", 593 | "log", 594 | "proc-macro2", 595 | "quote", 596 | "syn", 597 | "wasm-bindgen-shared", 598 | ] 599 | 600 | [[package]] 601 | name = "wasm-bindgen-futures" 602 | version = "0.4.50" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 605 | dependencies = [ 606 | "cfg-if", 607 | "js-sys", 608 | "once_cell", 609 | "wasm-bindgen", 610 | "web-sys", 611 | ] 612 | 613 | [[package]] 614 | name = "wasm-bindgen-macro" 615 | version = "0.2.100" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 618 | dependencies = [ 619 | "quote", 620 | "wasm-bindgen-macro-support", 621 | ] 622 | 623 | [[package]] 624 | name = "wasm-bindgen-macro-support" 625 | version = "0.2.100" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 628 | dependencies = [ 629 | "proc-macro2", 630 | "quote", 631 | "syn", 632 | "wasm-bindgen-backend", 633 | "wasm-bindgen-shared", 634 | ] 635 | 636 | [[package]] 637 | name = "wasm-bindgen-shared" 638 | version = "0.2.100" 639 | source = "registry+https://github.com/rust-lang/crates.io-index" 640 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 641 | dependencies = [ 642 | "unicode-ident", 643 | ] 644 | 645 | [[package]] 646 | name = "wasm-bindgen-test" 647 | version = "0.3.50" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" 650 | dependencies = [ 651 | "js-sys", 652 | "minicov", 653 | "wasm-bindgen", 654 | "wasm-bindgen-futures", 655 | "wasm-bindgen-test-macro", 656 | ] 657 | 658 | [[package]] 659 | name = "wasm-bindgen-test-macro" 660 | version = "0.3.50" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" 663 | dependencies = [ 664 | "proc-macro2", 665 | "quote", 666 | "syn", 667 | ] 668 | 669 | [[package]] 670 | name = "web-sys" 671 | version = "0.3.77" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 674 | dependencies = [ 675 | "js-sys", 676 | "wasm-bindgen", 677 | ] 678 | 679 | [[package]] 680 | name = "winapi-util" 681 | version = "0.1.9" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 684 | dependencies = [ 685 | "windows-sys", 686 | ] 687 | 688 | [[package]] 689 | name = "windows-core" 690 | version = "0.61.0" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" 693 | dependencies = [ 694 | "windows-implement", 695 | "windows-interface", 696 | "windows-link", 697 | "windows-result", 698 | "windows-strings", 699 | ] 700 | 701 | [[package]] 702 | name = "windows-implement" 703 | version = "0.60.0" 704 | source = "registry+https://github.com/rust-lang/crates.io-index" 705 | checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 706 | dependencies = [ 707 | "proc-macro2", 708 | "quote", 709 | "syn", 710 | ] 711 | 712 | [[package]] 713 | name = "windows-interface" 714 | version = "0.59.1" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 717 | dependencies = [ 718 | "proc-macro2", 719 | "quote", 720 | "syn", 721 | ] 722 | 723 | [[package]] 724 | name = "windows-link" 725 | version = "0.1.1" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 728 | 729 | [[package]] 730 | name = "windows-result" 731 | version = "0.3.2" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 734 | dependencies = [ 735 | "windows-link", 736 | ] 737 | 738 | [[package]] 739 | name = "windows-strings" 740 | version = "0.4.0" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" 743 | dependencies = [ 744 | "windows-link", 745 | ] 746 | 747 | [[package]] 748 | name = "windows-sys" 749 | version = "0.59.0" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 752 | dependencies = [ 753 | "windows-targets", 754 | ] 755 | 756 | [[package]] 757 | name = "windows-targets" 758 | version = "0.52.6" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 761 | dependencies = [ 762 | "windows_aarch64_gnullvm", 763 | "windows_aarch64_msvc", 764 | "windows_i686_gnu", 765 | "windows_i686_gnullvm", 766 | "windows_i686_msvc", 767 | "windows_x86_64_gnu", 768 | "windows_x86_64_gnullvm", 769 | "windows_x86_64_msvc", 770 | ] 771 | 772 | [[package]] 773 | name = "windows_aarch64_gnullvm" 774 | version = "0.52.6" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 777 | 778 | [[package]] 779 | name = "windows_aarch64_msvc" 780 | version = "0.52.6" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 783 | 784 | [[package]] 785 | name = "windows_i686_gnu" 786 | version = "0.52.6" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 789 | 790 | [[package]] 791 | name = "windows_i686_gnullvm" 792 | version = "0.52.6" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 795 | 796 | [[package]] 797 | name = "windows_i686_msvc" 798 | version = "0.52.6" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 801 | 802 | [[package]] 803 | name = "windows_x86_64_gnu" 804 | version = "0.52.6" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 807 | 808 | [[package]] 809 | name = "windows_x86_64_gnullvm" 810 | version = "0.52.6" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 813 | 814 | [[package]] 815 | name = "windows_x86_64_msvc" 816 | version = "0.52.6" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 819 | 820 | [[package]] 821 | name = "zerocopy" 822 | version = "0.7.35" 823 | source = "registry+https://github.com/rust-lang/crates.io-index" 824 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 825 | dependencies = [ 826 | "zerocopy-derive", 827 | ] 828 | 829 | [[package]] 830 | name = "zerocopy-derive" 831 | version = "0.7.35" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 834 | dependencies = [ 835 | "proc-macro2", 836 | "quote", 837 | "syn", 838 | ] 839 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arrow-wasm" 3 | version = "0.1.0" 4 | authors = ["Kyle Barron "] 5 | edition = "2021" 6 | description = "Core library for using Apache Arrow in Rust wasm-bindgen modules." 7 | readme = "README.md" 8 | repository = "https://github.com/kylebarron/parquet-wasm" 9 | license = "MIT OR Apache-2.0" 10 | keywords = ["webassembly", "arrow"] 11 | categories = ["wasm"] 12 | rust-version = "1.62" 13 | 14 | [lib] 15 | crate-type = ["cdylib", "rlib"] 16 | 17 | [features] 18 | default = ["all"] 19 | all = [ 20 | "data_type", 21 | "data", 22 | "field", 23 | "read_arrow_js", 24 | "record_batch", 25 | "schema", 26 | "table", 27 | "vector", 28 | ] 29 | 30 | # Include Data classes for contiguous Arrow memory 31 | data = [] 32 | 33 | # Include DataType classes for contiguous Arrow memory 34 | data_type = [] 35 | 36 | field = ["data_type"] 37 | 38 | # Include functionality to read Arrow JS objects directly. 39 | read_arrow_js = [] 40 | 41 | record_batch = ["table"] 42 | 43 | schema = [] 44 | 45 | # Include Table class 46 | table = [] 47 | 48 | # Include Vector classes for chunked Arrow memory 49 | vector = [] 50 | 51 | debug = ["dep:console_error_panic_hook"] 52 | 53 | [dependencies] 54 | wasm-bindgen = { version = "0.2.100", features = ["serde-serialize"] } 55 | 56 | # The `console_error_panic_hook` crate provides better debugging of panics by 57 | # logging them with `console.error`. This is great for development, but requires 58 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 59 | # code size when deploying. 60 | console_error_panic_hook = { version = "0.1.6", optional = true } 61 | 62 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 63 | # compared to the default allocator's ~10K. It is slower than the default 64 | # allocator, however. 65 | # if wee_alloc only saves 10KB, might not be worth the slower allocation speed? 66 | # wee_alloc = "0.4.5" 67 | 68 | js-sys = "0.3.77" 69 | getrandom = { version = "0.2.15", features = ["js"] } 70 | thiserror = "2.0" 71 | 72 | arrow-array = { version = "55", features = ["ffi"] } 73 | arrow-buffer = "55" 74 | arrow-data = "55" 75 | arrow-ipc = "55" 76 | arrow-schema = "55" 77 | 78 | serde = { version = "1.0", features = ["derive"] } 79 | serde-wasm-bindgen = "0.6" 80 | 81 | [dev-dependencies] 82 | wasm-bindgen-test = "0.3.50" 83 | 84 | [package.metadata.cargo-all-features] 85 | 86 | # Exclude certain features from the build matrix 87 | denylist = ["read_arrow_js"] 88 | 89 | [profile.release] 90 | # Tell `rustc` to optimize for small code size. 91 | # As of 3/15/22, opt-level = s was smallest 92 | # https://github.com/kylebarron/parquet-wasm/pull/48 93 | opt-level = "s" 94 | lto = true 95 | -------------------------------------------------------------------------------- /LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Kyle Barron 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # arrow-wasm 2 | 3 | Building block library for using Apache Arrow in Rust WebAssembly modules. 4 | -------------------------------------------------------------------------------- /example/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ahash" 7 | version = "0.8.6" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" 10 | dependencies = [ 11 | "cfg-if", 12 | "const-random", 13 | "getrandom", 14 | "once_cell", 15 | "version_check", 16 | "zerocopy", 17 | ] 18 | 19 | [[package]] 20 | name = "aho-corasick" 21 | version = "1.1.2" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" 24 | dependencies = [ 25 | "memchr", 26 | ] 27 | 28 | [[package]] 29 | name = "android-tzdata" 30 | version = "0.1.1" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 33 | 34 | [[package]] 35 | name = "android_system_properties" 36 | version = "0.1.5" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 39 | dependencies = [ 40 | "libc", 41 | ] 42 | 43 | [[package]] 44 | name = "arrow" 45 | version = "49.0.0" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "5bc25126d18a012146a888a0298f2c22e1150327bd2765fc76d710a556b2d614" 48 | dependencies = [ 49 | "ahash", 50 | "arrow-arith", 51 | "arrow-array", 52 | "arrow-buffer", 53 | "arrow-cast", 54 | "arrow-data", 55 | "arrow-ipc", 56 | "arrow-ord", 57 | "arrow-row", 58 | "arrow-schema", 59 | "arrow-select", 60 | "arrow-string", 61 | ] 62 | 63 | [[package]] 64 | name = "arrow-arith" 65 | version = "49.0.0" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "34ccd45e217ffa6e53bbb0080990e77113bdd4e91ddb84e97b77649810bcf1a7" 68 | dependencies = [ 69 | "arrow-array", 70 | "arrow-buffer", 71 | "arrow-data", 72 | "arrow-schema", 73 | "chrono", 74 | "half", 75 | "num", 76 | ] 77 | 78 | [[package]] 79 | name = "arrow-array" 80 | version = "49.0.0" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "6bda9acea48b25123c08340f3a8ac361aa0f74469bb36f5ee9acf923fce23e9d" 83 | dependencies = [ 84 | "ahash", 85 | "arrow-buffer", 86 | "arrow-data", 87 | "arrow-schema", 88 | "chrono", 89 | "half", 90 | "hashbrown", 91 | "num", 92 | ] 93 | 94 | [[package]] 95 | name = "arrow-buffer" 96 | version = "49.0.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "01a0fc21915b00fc6c2667b069c1b64bdd920982f426079bc4a7cab86822886c" 99 | dependencies = [ 100 | "bytes", 101 | "half", 102 | "num", 103 | ] 104 | 105 | [[package]] 106 | name = "arrow-cast" 107 | version = "49.0.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "5dc0368ed618d509636c1e3cc20db1281148190a78f43519487b2daf07b63b4a" 110 | dependencies = [ 111 | "arrow-array", 112 | "arrow-buffer", 113 | "arrow-data", 114 | "arrow-schema", 115 | "arrow-select", 116 | "base64", 117 | "chrono", 118 | "half", 119 | "lexical-core", 120 | "num", 121 | ] 122 | 123 | [[package]] 124 | name = "arrow-data" 125 | version = "49.0.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "907fafe280a3874474678c1858b9ca4cb7fd83fb8034ff5b6d6376205a08c634" 128 | dependencies = [ 129 | "arrow-buffer", 130 | "arrow-schema", 131 | "half", 132 | "num", 133 | ] 134 | 135 | [[package]] 136 | name = "arrow-ipc" 137 | version = "49.0.0" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "79a43d6808411886b8c7d4f6f7dd477029c1e77ffffffb7923555cc6579639cd" 140 | dependencies = [ 141 | "arrow-array", 142 | "arrow-buffer", 143 | "arrow-cast", 144 | "arrow-data", 145 | "arrow-schema", 146 | "flatbuffers", 147 | ] 148 | 149 | [[package]] 150 | name = "arrow-ord" 151 | version = "49.0.0" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "9b23b0e53c0db57c6749997fd343d4c0354c994be7eca67152dd2bdb9a3e1bb4" 154 | dependencies = [ 155 | "arrow-array", 156 | "arrow-buffer", 157 | "arrow-data", 158 | "arrow-schema", 159 | "arrow-select", 160 | "half", 161 | "num", 162 | ] 163 | 164 | [[package]] 165 | name = "arrow-row" 166 | version = "49.0.0" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "361249898d2d6d4a6eeb7484be6ac74977e48da12a4dd81a708d620cc558117a" 169 | dependencies = [ 170 | "ahash", 171 | "arrow-array", 172 | "arrow-buffer", 173 | "arrow-data", 174 | "arrow-schema", 175 | "half", 176 | "hashbrown", 177 | ] 178 | 179 | [[package]] 180 | name = "arrow-schema" 181 | version = "49.0.0" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "09e28a5e781bf1b0f981333684ad13f5901f4cd2f20589eab7cf1797da8fc167" 184 | dependencies = [ 185 | "bitflags 2.4.1", 186 | ] 187 | 188 | [[package]] 189 | name = "arrow-select" 190 | version = "49.0.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "4f6208466590960efc1d2a7172bc4ff18a67d6e25c529381d7f96ddaf0dc4036" 193 | dependencies = [ 194 | "ahash", 195 | "arrow-array", 196 | "arrow-buffer", 197 | "arrow-data", 198 | "arrow-schema", 199 | "num", 200 | ] 201 | 202 | [[package]] 203 | name = "arrow-string" 204 | version = "49.0.0" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "a4a48149c63c11c9ff571e50ab8f017d2a7cb71037a882b42f6354ed2da9acc7" 207 | dependencies = [ 208 | "arrow-array", 209 | "arrow-buffer", 210 | "arrow-data", 211 | "arrow-schema", 212 | "arrow-select", 213 | "num", 214 | "regex", 215 | "regex-syntax", 216 | ] 217 | 218 | [[package]] 219 | name = "arrow-wasm" 220 | version = "0.1.0" 221 | dependencies = [ 222 | "arrow", 223 | "arrow-schema", 224 | "getrandom", 225 | "js-sys", 226 | "thiserror", 227 | "wasm-bindgen", 228 | "web-sys", 229 | ] 230 | 231 | [[package]] 232 | name = "arrow-wasm-example" 233 | version = "0.1.0" 234 | dependencies = [ 235 | "arrow-wasm", 236 | "console_error_panic_hook", 237 | "js-sys", 238 | "wasm-bindgen", 239 | "wasm-bindgen-test", 240 | ] 241 | 242 | [[package]] 243 | name = "autocfg" 244 | version = "1.1.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 247 | 248 | [[package]] 249 | name = "base64" 250 | version = "0.21.5" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" 253 | 254 | [[package]] 255 | name = "bitflags" 256 | version = "1.3.2" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 259 | 260 | [[package]] 261 | name = "bitflags" 262 | version = "2.4.1" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" 265 | 266 | [[package]] 267 | name = "bumpalo" 268 | version = "3.14.0" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" 271 | 272 | [[package]] 273 | name = "bytes" 274 | version = "1.5.0" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" 277 | 278 | [[package]] 279 | name = "cc" 280 | version = "1.0.83" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 283 | dependencies = [ 284 | "libc", 285 | ] 286 | 287 | [[package]] 288 | name = "cfg-if" 289 | version = "1.0.0" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 292 | 293 | [[package]] 294 | name = "chrono" 295 | version = "0.4.31" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" 298 | dependencies = [ 299 | "android-tzdata", 300 | "iana-time-zone", 301 | "num-traits", 302 | "windows-targets", 303 | ] 304 | 305 | [[package]] 306 | name = "console_error_panic_hook" 307 | version = "0.1.7" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 310 | dependencies = [ 311 | "cfg-if", 312 | "wasm-bindgen", 313 | ] 314 | 315 | [[package]] 316 | name = "const-random" 317 | version = "0.1.17" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a" 320 | dependencies = [ 321 | "const-random-macro", 322 | ] 323 | 324 | [[package]] 325 | name = "const-random-macro" 326 | version = "0.1.16" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 329 | dependencies = [ 330 | "getrandom", 331 | "once_cell", 332 | "tiny-keccak", 333 | ] 334 | 335 | [[package]] 336 | name = "core-foundation-sys" 337 | version = "0.8.6" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" 340 | 341 | [[package]] 342 | name = "crunchy" 343 | version = "0.2.2" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 346 | 347 | [[package]] 348 | name = "flatbuffers" 349 | version = "23.5.26" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "4dac53e22462d78c16d64a1cd22371b54cc3fe94aa15e7886a2fa6e5d1ab8640" 352 | dependencies = [ 353 | "bitflags 1.3.2", 354 | "rustc_version", 355 | ] 356 | 357 | [[package]] 358 | name = "getrandom" 359 | version = "0.2.11" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" 362 | dependencies = [ 363 | "cfg-if", 364 | "js-sys", 365 | "libc", 366 | "wasi", 367 | "wasm-bindgen", 368 | ] 369 | 370 | [[package]] 371 | name = "half" 372 | version = "2.3.1" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" 375 | dependencies = [ 376 | "cfg-if", 377 | "crunchy", 378 | "num-traits", 379 | ] 380 | 381 | [[package]] 382 | name = "hashbrown" 383 | version = "0.14.3" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" 386 | 387 | [[package]] 388 | name = "iana-time-zone" 389 | version = "0.1.58" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" 392 | dependencies = [ 393 | "android_system_properties", 394 | "core-foundation-sys", 395 | "iana-time-zone-haiku", 396 | "js-sys", 397 | "wasm-bindgen", 398 | "windows-core", 399 | ] 400 | 401 | [[package]] 402 | name = "iana-time-zone-haiku" 403 | version = "0.1.2" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 406 | dependencies = [ 407 | "cc", 408 | ] 409 | 410 | [[package]] 411 | name = "itoa" 412 | version = "1.0.10" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" 415 | 416 | [[package]] 417 | name = "js-sys" 418 | version = "0.3.66" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" 421 | dependencies = [ 422 | "wasm-bindgen", 423 | ] 424 | 425 | [[package]] 426 | name = "lexical-core" 427 | version = "0.8.5" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" 430 | dependencies = [ 431 | "lexical-parse-float", 432 | "lexical-parse-integer", 433 | "lexical-util", 434 | "lexical-write-float", 435 | "lexical-write-integer", 436 | ] 437 | 438 | [[package]] 439 | name = "lexical-parse-float" 440 | version = "0.8.5" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" 443 | dependencies = [ 444 | "lexical-parse-integer", 445 | "lexical-util", 446 | "static_assertions", 447 | ] 448 | 449 | [[package]] 450 | name = "lexical-parse-integer" 451 | version = "0.8.6" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" 454 | dependencies = [ 455 | "lexical-util", 456 | "static_assertions", 457 | ] 458 | 459 | [[package]] 460 | name = "lexical-util" 461 | version = "0.8.5" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" 464 | dependencies = [ 465 | "static_assertions", 466 | ] 467 | 468 | [[package]] 469 | name = "lexical-write-float" 470 | version = "0.8.5" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" 473 | dependencies = [ 474 | "lexical-util", 475 | "lexical-write-integer", 476 | "static_assertions", 477 | ] 478 | 479 | [[package]] 480 | name = "lexical-write-integer" 481 | version = "0.8.5" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" 484 | dependencies = [ 485 | "lexical-util", 486 | "static_assertions", 487 | ] 488 | 489 | [[package]] 490 | name = "libc" 491 | version = "0.2.151" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" 494 | 495 | [[package]] 496 | name = "libm" 497 | version = "0.2.8" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 500 | 501 | [[package]] 502 | name = "log" 503 | version = "0.4.20" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 506 | 507 | [[package]] 508 | name = "memchr" 509 | version = "2.6.4" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 512 | 513 | [[package]] 514 | name = "num" 515 | version = "0.4.1" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" 518 | dependencies = [ 519 | "num-bigint", 520 | "num-complex", 521 | "num-integer", 522 | "num-iter", 523 | "num-rational", 524 | "num-traits", 525 | ] 526 | 527 | [[package]] 528 | name = "num-bigint" 529 | version = "0.4.4" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" 532 | dependencies = [ 533 | "autocfg", 534 | "num-integer", 535 | "num-traits", 536 | ] 537 | 538 | [[package]] 539 | name = "num-complex" 540 | version = "0.4.4" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" 543 | dependencies = [ 544 | "num-traits", 545 | ] 546 | 547 | [[package]] 548 | name = "num-integer" 549 | version = "0.1.45" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 552 | dependencies = [ 553 | "autocfg", 554 | "num-traits", 555 | ] 556 | 557 | [[package]] 558 | name = "num-iter" 559 | version = "0.1.43" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 562 | dependencies = [ 563 | "autocfg", 564 | "num-integer", 565 | "num-traits", 566 | ] 567 | 568 | [[package]] 569 | name = "num-rational" 570 | version = "0.4.1" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" 573 | dependencies = [ 574 | "autocfg", 575 | "num-bigint", 576 | "num-integer", 577 | "num-traits", 578 | ] 579 | 580 | [[package]] 581 | name = "num-traits" 582 | version = "0.2.17" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" 585 | dependencies = [ 586 | "autocfg", 587 | "libm", 588 | ] 589 | 590 | [[package]] 591 | name = "once_cell" 592 | version = "1.19.0" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 595 | 596 | [[package]] 597 | name = "proc-macro2" 598 | version = "1.0.70" 599 | source = "registry+https://github.com/rust-lang/crates.io-index" 600 | checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" 601 | dependencies = [ 602 | "unicode-ident", 603 | ] 604 | 605 | [[package]] 606 | name = "quote" 607 | version = "1.0.33" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 610 | dependencies = [ 611 | "proc-macro2", 612 | ] 613 | 614 | [[package]] 615 | name = "regex" 616 | version = "1.10.2" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" 619 | dependencies = [ 620 | "aho-corasick", 621 | "memchr", 622 | "regex-automata", 623 | "regex-syntax", 624 | ] 625 | 626 | [[package]] 627 | name = "regex-automata" 628 | version = "0.4.3" 629 | source = "registry+https://github.com/rust-lang/crates.io-index" 630 | checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" 631 | dependencies = [ 632 | "aho-corasick", 633 | "memchr", 634 | "regex-syntax", 635 | ] 636 | 637 | [[package]] 638 | name = "regex-syntax" 639 | version = "0.8.2" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 642 | 643 | [[package]] 644 | name = "rustc_version" 645 | version = "0.4.0" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 648 | dependencies = [ 649 | "semver", 650 | ] 651 | 652 | [[package]] 653 | name = "ryu" 654 | version = "1.0.16" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" 657 | 658 | [[package]] 659 | name = "scoped-tls" 660 | version = "1.0.1" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" 663 | 664 | [[package]] 665 | name = "semver" 666 | version = "1.0.20" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" 669 | 670 | [[package]] 671 | name = "serde" 672 | version = "1.0.193" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" 675 | dependencies = [ 676 | "serde_derive", 677 | ] 678 | 679 | [[package]] 680 | name = "serde_derive" 681 | version = "1.0.193" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" 684 | dependencies = [ 685 | "proc-macro2", 686 | "quote", 687 | "syn", 688 | ] 689 | 690 | [[package]] 691 | name = "serde_json" 692 | version = "1.0.108" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" 695 | dependencies = [ 696 | "itoa", 697 | "ryu", 698 | "serde", 699 | ] 700 | 701 | [[package]] 702 | name = "static_assertions" 703 | version = "1.1.0" 704 | source = "registry+https://github.com/rust-lang/crates.io-index" 705 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 706 | 707 | [[package]] 708 | name = "syn" 709 | version = "2.0.41" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" 712 | dependencies = [ 713 | "proc-macro2", 714 | "quote", 715 | "unicode-ident", 716 | ] 717 | 718 | [[package]] 719 | name = "thiserror" 720 | version = "1.0.50" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" 723 | dependencies = [ 724 | "thiserror-impl", 725 | ] 726 | 727 | [[package]] 728 | name = "thiserror-impl" 729 | version = "1.0.50" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" 732 | dependencies = [ 733 | "proc-macro2", 734 | "quote", 735 | "syn", 736 | ] 737 | 738 | [[package]] 739 | name = "tiny-keccak" 740 | version = "2.0.2" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 743 | dependencies = [ 744 | "crunchy", 745 | ] 746 | 747 | [[package]] 748 | name = "unicode-ident" 749 | version = "1.0.12" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 752 | 753 | [[package]] 754 | name = "version_check" 755 | version = "0.9.4" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 758 | 759 | [[package]] 760 | name = "wasi" 761 | version = "0.11.0+wasi-snapshot-preview1" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 764 | 765 | [[package]] 766 | name = "wasm-bindgen" 767 | version = "0.2.89" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" 770 | dependencies = [ 771 | "cfg-if", 772 | "serde", 773 | "serde_json", 774 | "wasm-bindgen-macro", 775 | ] 776 | 777 | [[package]] 778 | name = "wasm-bindgen-backend" 779 | version = "0.2.89" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" 782 | dependencies = [ 783 | "bumpalo", 784 | "log", 785 | "once_cell", 786 | "proc-macro2", 787 | "quote", 788 | "syn", 789 | "wasm-bindgen-shared", 790 | ] 791 | 792 | [[package]] 793 | name = "wasm-bindgen-futures" 794 | version = "0.4.39" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" 797 | dependencies = [ 798 | "cfg-if", 799 | "js-sys", 800 | "wasm-bindgen", 801 | "web-sys", 802 | ] 803 | 804 | [[package]] 805 | name = "wasm-bindgen-macro" 806 | version = "0.2.89" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" 809 | dependencies = [ 810 | "quote", 811 | "wasm-bindgen-macro-support", 812 | ] 813 | 814 | [[package]] 815 | name = "wasm-bindgen-macro-support" 816 | version = "0.2.89" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" 819 | dependencies = [ 820 | "proc-macro2", 821 | "quote", 822 | "syn", 823 | "wasm-bindgen-backend", 824 | "wasm-bindgen-shared", 825 | ] 826 | 827 | [[package]] 828 | name = "wasm-bindgen-shared" 829 | version = "0.2.89" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" 832 | 833 | [[package]] 834 | name = "wasm-bindgen-test" 835 | version = "0.3.39" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403" 838 | dependencies = [ 839 | "console_error_panic_hook", 840 | "js-sys", 841 | "scoped-tls", 842 | "wasm-bindgen", 843 | "wasm-bindgen-futures", 844 | "wasm-bindgen-test-macro", 845 | ] 846 | 847 | [[package]] 848 | name = "wasm-bindgen-test-macro" 849 | version = "0.3.39" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" 852 | dependencies = [ 853 | "proc-macro2", 854 | "quote", 855 | "syn", 856 | ] 857 | 858 | [[package]] 859 | name = "web-sys" 860 | version = "0.3.66" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" 863 | dependencies = [ 864 | "js-sys", 865 | "wasm-bindgen", 866 | ] 867 | 868 | [[package]] 869 | name = "windows-core" 870 | version = "0.51.1" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" 873 | dependencies = [ 874 | "windows-targets", 875 | ] 876 | 877 | [[package]] 878 | name = "windows-targets" 879 | version = "0.48.5" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 882 | dependencies = [ 883 | "windows_aarch64_gnullvm", 884 | "windows_aarch64_msvc", 885 | "windows_i686_gnu", 886 | "windows_i686_msvc", 887 | "windows_x86_64_gnu", 888 | "windows_x86_64_gnullvm", 889 | "windows_x86_64_msvc", 890 | ] 891 | 892 | [[package]] 893 | name = "windows_aarch64_gnullvm" 894 | version = "0.48.5" 895 | source = "registry+https://github.com/rust-lang/crates.io-index" 896 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 897 | 898 | [[package]] 899 | name = "windows_aarch64_msvc" 900 | version = "0.48.5" 901 | source = "registry+https://github.com/rust-lang/crates.io-index" 902 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 903 | 904 | [[package]] 905 | name = "windows_i686_gnu" 906 | version = "0.48.5" 907 | source = "registry+https://github.com/rust-lang/crates.io-index" 908 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 909 | 910 | [[package]] 911 | name = "windows_i686_msvc" 912 | version = "0.48.5" 913 | source = "registry+https://github.com/rust-lang/crates.io-index" 914 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 915 | 916 | [[package]] 917 | name = "windows_x86_64_gnu" 918 | version = "0.48.5" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 921 | 922 | [[package]] 923 | name = "windows_x86_64_gnullvm" 924 | version = "0.48.5" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 927 | 928 | [[package]] 929 | name = "windows_x86_64_msvc" 930 | version = "0.48.5" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 933 | 934 | [[package]] 935 | name = "zerocopy" 936 | version = "0.7.31" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" 939 | dependencies = [ 940 | "zerocopy-derive", 941 | ] 942 | 943 | [[package]] 944 | name = "zerocopy-derive" 945 | version = "0.7.31" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" 948 | dependencies = [ 949 | "proc-macro2", 950 | "quote", 951 | "syn", 952 | ] 953 | -------------------------------------------------------------------------------- /example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arrow-wasm-example" 3 | version = "0.1.0" 4 | authors = ["Kyle Barron "] 5 | edition = "2021" 6 | description = "Example of using arrow-wasm." 7 | readme = "README.md" 8 | repository = "https://github.com/kylebarron/parquet-wasm" 9 | license = "MIT OR Apache-2.0" 10 | keywords = ["webassembly", "arrow"] 11 | categories = ["wasm"] 12 | rust-version = "1.62" 13 | 14 | [lib] 15 | crate-type = ["cdylib", "rlib"] 16 | 17 | [dependencies] 18 | wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } 19 | 20 | # The `console_error_panic_hook` crate provides better debugging of panics by 21 | # logging them with `console.error`. This is great for development, but requires 22 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 23 | # code size when deploying. 24 | console_error_panic_hook = { version = "0.1.6", optional = true } 25 | 26 | js-sys = "0.3.60" 27 | arrow-wasm = { path = "../" } 28 | 29 | 30 | [dev-dependencies] 31 | wasm-bindgen-test = "0.3.31" 32 | 33 | [profile.release] 34 | # Tell `rustc` to optimize for small code size. 35 | # As of 3/15/22, opt-level = s was smallest 36 | # https://github.com/kylebarron/parquet-wasm/pull/48 37 | opt-level = "s" 38 | lto = true 39 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebarron/arrow-wasm/012447cab019efbb051cbd43ea5ad55a7549a4d8/example/README.md -------------------------------------------------------------------------------- /example/src/lib.rs: -------------------------------------------------------------------------------- 1 | // use arrow_wasm:: 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arrow-wasm", 3 | "packageManager": "yarn@3.3.1", 4 | "scripts": { 5 | "build": "bash ./scripts/build.sh", 6 | "build:test": "ENV='DEV' yarn build", 7 | "docs:build": "typedoc", 8 | "docs:publish": "gh-pages -d docs_build", 9 | "docs:serve": "cd docs_build && python -m http.server 8081", 10 | "docs:watch": "typedoc --watch" 11 | }, 12 | "volta": { 13 | "node": "20.7.0", 14 | "yarn": "3.6.3" 15 | }, 16 | "devDependencies": { 17 | "apache-arrow": "^15.0.0", 18 | "gh-pages": "^6.0.0", 19 | "typedoc": "^0.25.1", 20 | "typescript": "^5.2.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | rm -rf tmp_build pkg 3 | mkdir -p tmp_build 4 | 5 | if [ "$ENV" == "DEV" ]; then 6 | BUILD="--dev" 7 | FLAGS="--features debug" 8 | else 9 | BUILD="--release" 10 | FLAGS="" 11 | fi 12 | 13 | # Build node version into tmp_build/node 14 | echo "Building node" 15 | wasm-pack build \ 16 | $BUILD \ 17 | --out-dir tmp_build/node \ 18 | --target nodejs \ 19 | --features all \ 20 | $FLAGS & 21 | [ -n "$CI" ] && wait; 22 | 23 | # Build web version into tmp_build/esm 24 | echo "Building esm" 25 | wasm-pack build \ 26 | $BUILD \ 27 | --out-dir tmp_build/esm \ 28 | --target web \ 29 | --features all \ 30 | $FLAGS & 31 | [ -n "$CI" ] && wait; 32 | 33 | # Build bundler version into tmp_build/bundler 34 | echo "Building bundler" 35 | wasm-pack build \ 36 | $BUILD \ 37 | --out-dir tmp_build/bundler \ 38 | --target bundler \ 39 | --features all \ 40 | $FLAGS & 41 | wait 42 | 43 | # Copy files into pkg/ 44 | mkdir -p pkg/{node,esm,bundler} 45 | 46 | cp tmp_build/bundler/arrow* pkg/bundler/ 47 | cp tmp_build/esm/arrow* pkg/esm 48 | cp tmp_build/node/arrow* pkg/node 49 | 50 | cp tmp_build/bundler/{package.json,LICENSE_APACHE,LICENSE_MIT,README.md} pkg/ 51 | 52 | # Create minimal package.json in esm/ folder with type: module 53 | echo '{"type": "module"}' > pkg/esm/package.json 54 | 55 | # Create an esm2/ directory without import.meta.url in the JS ESM wrapper 56 | cp -r pkg/esm pkg/esm2 57 | sed '/import.meta.url/ s|input|// input|' pkg/esm2/arrow_wasm.js > pkg/esm2/arrow_wasm_new.js 58 | mv pkg/esm2/arrow_wasm_new.js pkg/esm2/arrow_wasm.js 59 | 60 | # Update files array in package.json using JQ 61 | jq '.files = ["*"] | .module="bundler/arrow_wasm.js" | .types="bundler/arrow_wasm.d.ts"' pkg/package.json > pkg/package.json.tmp 62 | 63 | # Overwrite existing package.json file 64 | mv pkg/package.json.tmp pkg/package.json 65 | 66 | rm -rf tmp_build 67 | -------------------------------------------------------------------------------- /src/arrow_js/data.rs: -------------------------------------------------------------------------------- 1 | use arrow_buffer::Buffer; 2 | use arrow_data::ArrayData; 3 | use arrow_schema::DataType; 4 | use wasm_bindgen::prelude::*; 5 | 6 | use crate::arrow_js::r#type::{import_data_type, JSDataType}; 7 | 8 | #[wasm_bindgen] 9 | extern "C" { 10 | pub type JSData; 11 | 12 | #[wasm_bindgen(method, getter, js_name = "type")] 13 | pub fn data_type(this: &JSData) -> JSDataType; 14 | 15 | #[wasm_bindgen(method, getter)] 16 | pub fn length(this: &JSData) -> usize; 17 | 18 | #[wasm_bindgen(method, getter)] 19 | pub fn offset(this: &JSData) -> usize; 20 | 21 | #[wasm_bindgen(method, getter)] 22 | pub fn stride(this: &JSData) -> usize; 23 | 24 | #[wasm_bindgen(method, getter)] 25 | pub fn children(this: &JSData) -> Vec; 26 | 27 | #[wasm_bindgen(method, getter)] 28 | pub fn values(this: &JSData) -> TypedArrayLike; 29 | 30 | #[wasm_bindgen(method, getter, js_name = "typeIds")] 31 | pub fn type_ids(this: &JSData) -> TypedArrayLike; 32 | 33 | #[wasm_bindgen(method, getter, js_name = "nullBitmap")] 34 | pub fn null_bitmap(this: &JSData) -> Option; 35 | 36 | #[wasm_bindgen(method, getter, js_name = "valueOffsets")] 37 | pub fn value_offsets(this: &JSData) -> TypedArrayLike; 38 | 39 | pub type TypedArrayLike; 40 | 41 | /// The buffer accessor property represents the `ArrayBuffer` referenced 42 | /// by a `TypedArray` at construction time. 43 | #[wasm_bindgen(getter, method)] 44 | pub fn buffer(this: &TypedArrayLike) -> js_sys::ArrayBuffer; 45 | 46 | /// The byteLength accessor property represents the length (in bytes) of a 47 | /// typed array. 48 | #[wasm_bindgen(method, getter, js_name = byteLength)] 49 | pub fn byte_length(this: &TypedArrayLike) -> u32; 50 | 51 | /// The byteOffset accessor property represents the offset (in bytes) of a 52 | /// typed array from the start of its `ArrayBuffer`. 53 | #[wasm_bindgen(method, getter, js_name = byteOffset)] 54 | pub fn byte_offset(this: &TypedArrayLike) -> u32; 55 | } 56 | 57 | fn copy_null_bitmap(js_data: &JSData) -> Option { 58 | js_data.null_bitmap().and_then(|arr| { 59 | let buf = arr.to_vec(); 60 | // Arrow JS often stores an empty Uint8Array for a non-null array. So here, if the buffer 61 | // is of length 0, we return None, to signify fully valid. 62 | if buf.is_empty() { 63 | None 64 | } else { 65 | Some(Buffer::from_vec(buf)) 66 | } 67 | }) 68 | } 69 | 70 | fn copy_typed_array_like(arr: &TypedArrayLike) -> Buffer { 71 | let uint8_view = js_sys::Uint8Array::new_with_byte_offset_and_length( 72 | &arr.buffer().into(), 73 | arr.byte_offset(), 74 | arr.byte_length(), 75 | ); 76 | Buffer::from_vec(uint8_view.to_vec()) 77 | } 78 | 79 | fn copy_values(js_data: &JSData) -> Buffer { 80 | copy_typed_array_like(&js_data.values()) 81 | } 82 | 83 | fn copy_value_offsets(js_data: &JSData) -> Buffer { 84 | copy_typed_array_like(js_data.value_offsets().unchecked_ref()) 85 | } 86 | 87 | pub fn import_data(js_data: &JSData) -> ArrayData { 88 | let mut child_data = vec![]; 89 | for child in js_data.children() { 90 | child_data.push(import_data(&child)); 91 | } 92 | 93 | let data_type = import_data_type(&js_data.data_type()); 94 | 95 | // TODO: support dictionary 96 | let buffers = match data_type.is_primitive() { 97 | true => vec![copy_values(js_data)], 98 | false => match data_type { 99 | DataType::Null => vec![], 100 | DataType::Boolean => vec![copy_values(js_data)], 101 | DataType::Binary | DataType::LargeBinary | DataType::Utf8 | DataType::LargeUtf8 => { 102 | vec![copy_value_offsets(js_data), copy_values(js_data)] 103 | } 104 | DataType::List(_) | DataType::LargeList(_) => vec![copy_value_offsets(js_data)], 105 | DataType::FixedSizeBinary(_) | DataType::FixedSizeList(_, _) | DataType::Struct(_) => { 106 | vec![] 107 | } 108 | DataType::Union(_fields, _mode) => { 109 | todo!() 110 | } 111 | _ => unreachable!(), 112 | }, 113 | }; 114 | 115 | ArrayData::try_new( 116 | data_type, 117 | js_data.length(), 118 | copy_null_bitmap(js_data), 119 | js_data.offset(), 120 | buffers, 121 | child_data, 122 | ) 123 | .unwrap() 124 | } 125 | -------------------------------------------------------------------------------- /src/arrow_js/enum.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen] 4 | pub enum UnionMode { 5 | Sparse = 0, 6 | Dense = 1, 7 | } 8 | 9 | #[wasm_bindgen] 10 | pub enum Precision { 11 | Half = 0, 12 | Single = 1, 13 | Double = 2, 14 | } 15 | 16 | #[wasm_bindgen] 17 | pub enum DateUnit { 18 | Day = 0, 19 | Millisecond = 1, 20 | } 21 | 22 | #[wasm_bindgen] 23 | pub enum TimeUnit { 24 | Second = 0, 25 | Millisecond = 1, 26 | Microsecond = 2, 27 | Nanosecond = 3, 28 | } 29 | 30 | #[wasm_bindgen] 31 | pub enum IntervalUnit { 32 | YearMonth = 0, 33 | DayTime = 1, 34 | MonthDayNano = 2, 35 | } 36 | 37 | #[wasm_bindgen(js_name = Type)] 38 | pub enum r#Type { 39 | /// The default placeholder type 40 | NONE = 0, 41 | /// A NULL type having no physical storage 42 | Null = 1, 43 | /// Signed or unsigned 8, 16, 32, or 64-bit little-endian integer 44 | Int = 2, 45 | /// 2, 4, or 8-byte floating point value 46 | Float = 3, 47 | /// Variable-length bytes (no guarantee of UTF8-ness) 48 | Binary = 4, 49 | /// UTF8 variable-length string as List 50 | Utf8 = 5, 51 | /// Boolean as 1 bit, LSB bit-packed ordering 52 | Bool = 6, 53 | /// Precision-and-scale-based decimal type. Storage type depends on the parameters. 54 | Decimal = 7, 55 | /// int32_t days or int64_t milliseconds since the UNIX epoch 56 | Date = 8, 57 | /// Time as signed 32 or 64-bit integer, representing either seconds, milliseconds, 58 | /// microseconds, or nanoseconds since midnight since midnight 59 | Time = 9, 60 | /// Exact timestamp encoded with int64 since UNIX epoch (Default unit millisecond) 61 | Timestamp = 10, 62 | /// YEAR_MONTH or DAY_TIME interval in SQL style 63 | Interval = 11, 64 | /// A list of some logical data type 65 | List = 12, 66 | /// Struct of logical types 67 | Struct = 13, 68 | /// Union of logical types 69 | Union = 14, 70 | /// Fixed-size binary. Each value occupies the same number of bytes 71 | FixedSizeBinary = 15, 72 | /// Fixed-size list. Each value occupies the same number of bytes 73 | FixedSizeList = 16, 74 | /// Map of named logical types 75 | Map = 17, 76 | /// Measure of elapsed time in either seconds, milliseconds, microseconds or nanoseconds. 77 | Duration = 18, 78 | } 79 | 80 | #[wasm_bindgen] 81 | pub enum BufferType { 82 | /** 83 | * used in List type, Dense Union and variable length primitive types (String, Binary) 84 | */ 85 | Offset = 0, 86 | 87 | /** 88 | * actual data, either fixed width primitive types in slots or variable width delimited by an OFFSET vector 89 | */ 90 | Data = 1, 91 | 92 | /** 93 | * Bit vector indicating if each value is null 94 | */ 95 | Validity = 2, 96 | 97 | /** 98 | * Type vector used in Union type 99 | */ 100 | Type = 3, 101 | } 102 | -------------------------------------------------------------------------------- /src/arrow_js/field.rs: -------------------------------------------------------------------------------- 1 | use arrow_schema::Field; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::arrow_js::r#type::{import_data_type, JSDataType}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | pub type JSField; 9 | 10 | #[wasm_bindgen(method, getter, js_name = "type")] 11 | pub fn data_type(this: &JSField) -> JSDataType; 12 | 13 | #[wasm_bindgen(method, getter)] 14 | pub fn name(this: &JSField) -> String; 15 | 16 | #[wasm_bindgen(method, getter)] 17 | pub fn nullable(this: &JSField) -> bool; 18 | 19 | #[wasm_bindgen(method, getter)] 20 | pub fn metadata(this: &JSField) -> js_sys::Map; 21 | 22 | } 23 | 24 | pub fn import_field(js_field: &JSField) -> Field { 25 | let data_type = import_data_type(&js_field.data_type()); 26 | Field::new(js_field.name(), data_type, js_field.nullable()) 27 | .with_metadata(serde_wasm_bindgen::from_value(js_field.metadata().into()).unwrap()) 28 | } 29 | -------------------------------------------------------------------------------- /src/arrow_js/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod data; 2 | pub mod r#enum; 3 | pub mod field; 4 | pub mod record_batch; 5 | pub mod schema; 6 | pub mod table; 7 | pub mod r#type; 8 | -------------------------------------------------------------------------------- /src/arrow_js/record_batch.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use crate::error::WasmResult; 4 | use arrow_array::cast::AsArray; 5 | use arrow_array::make_array; 6 | use arrow_schema::SchemaRef; 7 | // use arrow::record_batch::RecordBatch; 8 | use crate::record_batch::RecordBatch; 9 | use wasm_bindgen::prelude::*; 10 | 11 | use crate::arrow_js::data::{import_data, JSData}; 12 | use crate::arrow_js::schema::{import_schema, JSSchema}; 13 | 14 | #[wasm_bindgen] 15 | extern "C" { 16 | pub type JSRecordBatch; 17 | 18 | #[wasm_bindgen(method, getter)] 19 | pub fn schema(this: &JSRecordBatch) -> JSSchema; 20 | 21 | #[wasm_bindgen(method, getter)] 22 | pub fn data(this: &JSRecordBatch) -> JSData; 23 | 24 | } 25 | 26 | impl RecordBatch { 27 | pub fn from_js(js_record_batch: &JSRecordBatch) -> WasmResult { 28 | let schema = import_schema(&js_record_batch.schema()); 29 | let data = import_data(&js_record_batch.data()); 30 | let dyn_arr = make_array(data); 31 | let struct_arr = dyn_arr.as_struct(); 32 | 33 | let batch = 34 | arrow_array::RecordBatch::try_new(Arc::new(schema), struct_arr.columns().to_vec())?; 35 | Ok(RecordBatch::new(batch)) 36 | } 37 | 38 | pub fn from_js_with_schema( 39 | js_record_batch: &JSRecordBatch, 40 | schema: SchemaRef, 41 | ) -> WasmResult { 42 | let data = import_data(&js_record_batch.data()); 43 | let dyn_arr = make_array(data); 44 | let struct_arr = dyn_arr.as_struct(); 45 | 46 | let batch = arrow_array::RecordBatch::try_new(schema, struct_arr.columns().to_vec())?; 47 | Ok(RecordBatch::new(batch)) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/arrow_js/schema.rs: -------------------------------------------------------------------------------- 1 | use arrow_schema::Schema; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::arrow_js::field::{import_field, JSField}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | pub type JSSchema; 9 | 10 | #[wasm_bindgen(method, getter)] 11 | pub fn fields(this: &JSSchema) -> Vec; 12 | 13 | #[wasm_bindgen(method, getter)] 14 | pub fn metadata(this: &JSSchema) -> js_sys::Map; 15 | 16 | } 17 | 18 | pub fn import_schema(js_schema: &JSSchema) -> Schema { 19 | let fields: Vec<_> = js_schema 20 | .fields() 21 | .into_iter() 22 | .map(|js_field| import_field(&js_field)) 23 | .collect(); 24 | Schema::new_with_metadata( 25 | fields, 26 | serde_wasm_bindgen::from_value(js_schema.metadata().into()).unwrap(), 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /src/arrow_js/table.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use wasm_bindgen::prelude::*; 4 | 5 | use crate::arrow_js::record_batch::JSRecordBatch; 6 | use crate::arrow_js::schema::{import_schema, JSSchema}; 7 | use crate::error::WasmResult; 8 | use crate::{RecordBatch, Table}; 9 | 10 | #[wasm_bindgen] 11 | extern "C" { 12 | pub type JSTable; 13 | 14 | #[wasm_bindgen(method, getter)] 15 | pub fn schema(this: &JSTable) -> JSSchema; 16 | 17 | #[wasm_bindgen(method, getter)] 18 | pub fn batches(this: &JSTable) -> Vec; 19 | 20 | } 21 | 22 | impl Table { 23 | /// Creates a table from a JSTable. 24 | pub fn from_js(js_table: &JSTable) -> WasmResult { 25 | let schema = Arc::new(import_schema(&js_table.schema())); 26 | let batches = js_table 27 | .batches() 28 | .into_iter() 29 | .map(|batch| Ok(RecordBatch::from_js_with_schema(&batch, schema.clone())?.into_inner())) 30 | .collect::>>()?; 31 | Ok(Table::new(schema, batches)) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/arrow_js/type.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use arrow_schema::{DataType, UnionFields}; 4 | use wasm_bindgen::prelude::*; 5 | 6 | use crate::arrow_js::field::{import_field, JSField}; 7 | 8 | #[wasm_bindgen] 9 | extern "C" { 10 | pub type JSDataType; 11 | 12 | #[wasm_bindgen(method, getter, js_name = "typeId")] 13 | pub fn type_id(this: &JSDataType) -> super::r#enum::Type; 14 | 15 | // Any data types containing data need to be defined separately: 16 | 17 | /// Arrow.Int 18 | pub type JSInt; 19 | 20 | #[wasm_bindgen(method, getter, js_name = "bitWidth")] 21 | pub fn bit_width(this: &JSInt) -> u8; 22 | 23 | #[wasm_bindgen(method, getter, js_name = "isSigned")] 24 | pub fn is_signed(this: &JSInt) -> bool; 25 | 26 | /// Arrow.Float 27 | pub type JSFloat; 28 | 29 | #[wasm_bindgen(method, getter)] 30 | pub fn precision(this: &JSFloat) -> super::r#enum::Precision; 31 | 32 | pub type JSDecimal; 33 | 34 | #[wasm_bindgen(method, getter)] 35 | pub fn scale(this: &JSDecimal) -> i8; 36 | 37 | #[wasm_bindgen(method, getter)] 38 | pub fn precision(this: &JSDecimal) -> u8; 39 | 40 | #[wasm_bindgen(method, getter, js_name = "bitWidth")] 41 | pub fn bit_width(this: &JSDecimal) -> usize; 42 | 43 | pub type JSDate_; 44 | 45 | #[wasm_bindgen(method, getter)] 46 | pub fn unit(this: &JSDate_) -> super::r#enum::DateUnit; 47 | 48 | pub type JSTime; 49 | 50 | #[wasm_bindgen(method, getter)] 51 | pub fn unit(this: &JSTime) -> super::r#enum::TimeUnit; 52 | 53 | pub type JSTimestamp; 54 | 55 | #[wasm_bindgen(method, getter)] 56 | pub fn unit(this: &JSTimestamp) -> super::r#enum::TimeUnit; 57 | 58 | #[wasm_bindgen(method, getter)] 59 | pub fn timezone(this: &JSTimestamp) -> Option; 60 | 61 | pub type JSInterval; 62 | 63 | #[wasm_bindgen(method, getter)] 64 | pub fn unit(this: &JSInterval) -> super::r#enum::IntervalUnit; 65 | 66 | pub type JSDuration; 67 | 68 | #[wasm_bindgen(method, getter)] 69 | pub fn unit(this: &JSDuration) -> super::r#enum::TimeUnit; 70 | 71 | pub type JSList; 72 | 73 | #[wasm_bindgen(method, getter)] 74 | pub fn children(this: &JSList) -> Vec; 75 | 76 | pub type JSStruct; 77 | 78 | #[wasm_bindgen(method, getter)] 79 | pub fn children(this: &JSStruct) -> Vec; 80 | 81 | pub type JSUnion; 82 | 83 | #[wasm_bindgen(method, getter)] 84 | pub fn mode(this: &JSUnion) -> super::r#enum::UnionMode; 85 | 86 | #[wasm_bindgen(method, getter, js_name = "typeIds")] 87 | pub fn type_ids(this: &JSUnion) -> js_sys::Int32Array; 88 | 89 | #[wasm_bindgen(method, getter)] 90 | pub fn children(this: &JSUnion) -> Vec; 91 | 92 | pub type JSFixedSizeBinary; 93 | 94 | #[wasm_bindgen(method, getter, js_name = "byteWidth")] 95 | pub fn byte_width(this: &JSFixedSizeBinary) -> i32; 96 | 97 | pub type JSFixedSizeList; 98 | 99 | #[wasm_bindgen(method, getter, js_name = "listSize")] 100 | pub fn list_size(this: &JSFixedSizeList) -> i32; 101 | 102 | #[wasm_bindgen(method, getter)] 103 | pub fn children(this: &JSFixedSizeList) -> Vec; 104 | 105 | pub type JSMap_; 106 | 107 | #[wasm_bindgen(method, getter, js_name = "keysSorted")] 108 | pub fn keys_sorted(this: &JSMap_) -> bool; 109 | 110 | #[wasm_bindgen(method, getter)] 111 | pub fn children(this: &JSMap_) -> Vec; 112 | 113 | } 114 | 115 | fn import_int(js_type: &JSInt) -> DataType { 116 | match (js_type.is_signed(), js_type.bit_width()) { 117 | (true, 8) => DataType::Int8, 118 | (true, 16) => DataType::Int16, 119 | (true, 32) => DataType::Int32, 120 | (true, 64) => DataType::Int64, 121 | (false, 8) => DataType::UInt8, 122 | (false, 16) => DataType::UInt16, 123 | (false, 32) => DataType::UInt32, 124 | (false, 64) => DataType::UInt64, 125 | _ => unreachable!(), 126 | } 127 | } 128 | 129 | fn import_float(js_type: &JSFloat) -> DataType { 130 | use super::r#enum::Precision; 131 | 132 | match js_type.precision() { 133 | Precision::Half => DataType::Float16, 134 | Precision::Single => DataType::Float32, 135 | Precision::Double => DataType::Float64, 136 | } 137 | } 138 | 139 | fn import_decimal(js_type: &JSDecimal) -> DataType { 140 | match js_type.bit_width() { 141 | 128 => DataType::Decimal128(js_type.precision(), js_type.scale()), 142 | 256 => DataType::Decimal256(js_type.precision(), js_type.scale()), 143 | _ => unreachable!(), 144 | } 145 | } 146 | 147 | fn import_date(js_type: &JSDate_) -> DataType { 148 | use super::r#enum::DateUnit; 149 | 150 | match js_type.unit() { 151 | DateUnit::Day => DataType::Date32, 152 | DateUnit::Millisecond => DataType::Date64, 153 | } 154 | } 155 | 156 | fn import_time(js_type: &JSTime) -> DataType { 157 | use super::r#enum::TimeUnit; 158 | 159 | match js_type.unit() { 160 | TimeUnit::Second => DataType::Time32(arrow_schema::TimeUnit::Second), 161 | TimeUnit::Millisecond => DataType::Time32(arrow_schema::TimeUnit::Millisecond), 162 | TimeUnit::Microsecond => DataType::Time64(arrow_schema::TimeUnit::Microsecond), 163 | TimeUnit::Nanosecond => DataType::Time64(arrow_schema::TimeUnit::Nanosecond), 164 | } 165 | } 166 | 167 | fn import_timestamp(js_type: &JSTimestamp) -> DataType { 168 | use super::r#enum::TimeUnit; 169 | 170 | match js_type.unit() { 171 | TimeUnit::Second => DataType::Timestamp( 172 | arrow_schema::TimeUnit::Second, 173 | js_type.timezone().map(|s| s.into()), 174 | ), 175 | TimeUnit::Millisecond => DataType::Timestamp( 176 | arrow_schema::TimeUnit::Millisecond, 177 | js_type.timezone().map(|s| s.into()), 178 | ), 179 | TimeUnit::Microsecond => DataType::Timestamp( 180 | arrow_schema::TimeUnit::Microsecond, 181 | js_type.timezone().map(|s| s.into()), 182 | ), 183 | TimeUnit::Nanosecond => DataType::Timestamp( 184 | arrow_schema::TimeUnit::Nanosecond, 185 | js_type.timezone().map(|s| s.into()), 186 | ), 187 | } 188 | } 189 | 190 | fn import_interval(js_type: &JSInterval) -> DataType { 191 | use super::r#enum::IntervalUnit; 192 | 193 | match js_type.unit() { 194 | IntervalUnit::DayTime => DataType::Interval(arrow_schema::IntervalUnit::DayTime), 195 | IntervalUnit::YearMonth => DataType::Interval(arrow_schema::IntervalUnit::YearMonth), 196 | IntervalUnit::MonthDayNano => DataType::Interval(arrow_schema::IntervalUnit::MonthDayNano), 197 | } 198 | } 199 | 200 | fn import_duration(js_type: &JSDuration) -> DataType { 201 | use super::r#enum::TimeUnit; 202 | 203 | match js_type.unit() { 204 | TimeUnit::Second => DataType::Duration(arrow_schema::TimeUnit::Second), 205 | TimeUnit::Millisecond => DataType::Duration(arrow_schema::TimeUnit::Millisecond), 206 | TimeUnit::Microsecond => DataType::Duration(arrow_schema::TimeUnit::Microsecond), 207 | TimeUnit::Nanosecond => DataType::Duration(arrow_schema::TimeUnit::Nanosecond), 208 | } 209 | } 210 | 211 | fn import_list(js_type: &JSList) -> DataType { 212 | let mut children = js_type.children(); 213 | assert_eq!(children.len(), 1); 214 | let child = children.pop().unwrap(); 215 | let field = import_field(&child); 216 | DataType::List(Arc::new(field)) 217 | } 218 | 219 | fn import_struct(js_type: &JSStruct) -> DataType { 220 | let fields = js_type 221 | .children() 222 | .into_iter() 223 | .map(|child| import_field(&child)) 224 | .collect(); 225 | DataType::Struct(fields) 226 | } 227 | 228 | fn import_union(js_type: &JSUnion) -> DataType { 229 | use super::r#enum::UnionMode; 230 | 231 | let fields: Vec = js_type 232 | .children() 233 | .into_iter() 234 | .map(|child| import_field(&child)) 235 | .collect(); 236 | let type_ids: Vec = js_type 237 | .type_ids() 238 | .to_vec() 239 | .into_iter() 240 | .map(|val| i8::try_from(val).unwrap()) 241 | .collect(); 242 | 243 | let union_fields = UnionFields::new(type_ids, fields); 244 | match js_type.mode() { 245 | UnionMode::Dense => DataType::Union(union_fields, arrow_schema::UnionMode::Dense), 246 | UnionMode::Sparse => DataType::Union(union_fields, arrow_schema::UnionMode::Sparse), 247 | } 248 | } 249 | 250 | fn import_fixed_size_binary(js_type: &JSFixedSizeBinary) -> DataType { 251 | DataType::FixedSizeBinary(js_type.byte_width()) 252 | } 253 | 254 | fn import_fixed_size_list(js_type: &JSFixedSizeList) -> DataType { 255 | let mut children = js_type.children(); 256 | assert_eq!(children.len(), 1); 257 | let child = children.pop().unwrap(); 258 | let field = import_field(&child); 259 | DataType::FixedSizeList(Arc::new(field), js_type.list_size()) 260 | } 261 | 262 | fn import_map(js_type: &JSMap_) -> DataType { 263 | let mut children = js_type.children(); 264 | assert_eq!(children.len(), 1); 265 | let child = children.pop().unwrap(); 266 | let field = import_field(&child); 267 | DataType::Map(Arc::new(field), js_type.keys_sorted()) 268 | } 269 | 270 | pub fn import_data_type(js_type: &JSDataType) -> DataType { 271 | use super::r#enum::Type; 272 | 273 | match js_type.type_id() { 274 | // Type None should never be initialized 275 | Type::NONE => panic!("Type None"), 276 | Type::Null => DataType::Null, 277 | Type::Int => import_int(js_type.unchecked_ref()), 278 | Type::Float => import_float(js_type.unchecked_ref()), 279 | Type::Binary => DataType::Binary, 280 | Type::Utf8 => DataType::Utf8, 281 | Type::Bool => DataType::Boolean, 282 | Type::Decimal => import_decimal(js_type.unchecked_ref()), 283 | Type::Date => import_date(js_type.unchecked_ref()), 284 | Type::Time => import_time(js_type.unchecked_ref()), 285 | Type::Timestamp => import_timestamp(js_type.unchecked_ref()), 286 | Type::Interval => import_interval(js_type.unchecked_ref()), 287 | Type::Duration => import_duration(js_type.unchecked_ref()), 288 | Type::List => import_list(js_type.unchecked_ref()), 289 | Type::Struct => import_struct(js_type.unchecked_ref()), 290 | Type::Union => import_union(js_type.unchecked_ref()), 291 | Type::FixedSizeBinary => import_fixed_size_binary(js_type.unchecked_ref()), 292 | Type::FixedSizeList => import_fixed_size_list(js_type.unchecked_ref()), 293 | Type::Map => import_map(js_type.unchecked_ref()), 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /src/data.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use arrow_array::cast::AsArray; 4 | use arrow_array::types::{ 5 | Float32Type, Float64Type, Int16Type, Int32Type, Int64Type, Int8Type, UInt16Type, UInt32Type, 6 | UInt64Type, UInt8Type, 7 | }; 8 | use arrow_array::{make_array, Array, ArrayRef}; 9 | use arrow_schema::DataType; 10 | use arrow_schema::{Field, FieldRef}; 11 | use wasm_bindgen::prelude::*; 12 | 13 | use crate::error::{ArrowWasmError, WasmResult}; 14 | use crate::ffi::FFIData; 15 | 16 | /// A representation of an Arrow `Data` instance in WebAssembly memory. 17 | /// 18 | /// This has the same underlying representation as an Arrow JS `Data` object. 19 | #[wasm_bindgen] 20 | pub struct Data { 21 | array: ArrayRef, 22 | field: FieldRef, 23 | } 24 | 25 | #[wasm_bindgen] 26 | impl Data { 27 | /// Export this to FFI. 28 | #[wasm_bindgen(js_name = toFFI)] 29 | pub fn to_ffi(&self) -> WasmResult { 30 | let ffi_schema = arrow_array::ffi::FFI_ArrowSchema::try_from(&self.field)?; 31 | let ffi_array = arrow_array::ffi::FFI_ArrowArray::new(&self.array.to_data()); 32 | Ok(FFIData::new(Box::new(ffi_array), Box::new(ffi_schema))) 33 | } 34 | 35 | /// Copy the values of this `Data` instance to a TypedArray in the JavaScript heap. 36 | /// 37 | /// This will silently ignore any null values. This will error on non-primitive data types for 38 | /// which a TypedArray does not exist in JavaScript. 39 | #[wasm_bindgen(js_name = toTypedArray)] 40 | pub fn to_typed_array(&self) -> WasmResult { 41 | macro_rules! impl_to_typed_array { 42 | ($arrow_type:ty, $js_array:ty) => {{ 43 | let values = self.array.as_primitive::<$arrow_type>().values().as_ref(); 44 | Ok(<$js_array>::from(values).into()) 45 | }}; 46 | } 47 | 48 | match self.array.data_type() { 49 | DataType::UInt8 => impl_to_typed_array!(UInt8Type, js_sys::Uint8Array), 50 | DataType::UInt16 => impl_to_typed_array!(UInt16Type, js_sys::Uint16Array), 51 | DataType::UInt32 => impl_to_typed_array!(UInt32Type, js_sys::Uint32Array), 52 | DataType::UInt64 => impl_to_typed_array!(UInt64Type, js_sys::BigUint64Array), 53 | DataType::Int8 => impl_to_typed_array!(Int8Type, js_sys::Int8Array), 54 | DataType::Int16 => impl_to_typed_array!(Int16Type, js_sys::Int16Array), 55 | DataType::Int32 => impl_to_typed_array!(Int32Type, js_sys::Int32Array), 56 | DataType::Int64 => impl_to_typed_array!(Int64Type, js_sys::BigInt64Array), 57 | DataType::Float32 => impl_to_typed_array!(Float32Type, js_sys::Float32Array), 58 | DataType::Float64 => impl_to_typed_array!(Float64Type, js_sys::Float64Array), 59 | dt => { 60 | Err(ArrowWasmError::InternalError(format!("Unexpected data type: {}", dt)).into()) 61 | } 62 | } 63 | } 64 | } 65 | 66 | impl Data { 67 | pub fn new(array: ArrayRef, field: FieldRef) -> Self { 68 | assert_eq!(array.data_type(), field.data_type()); 69 | Self { array, field } 70 | } 71 | 72 | pub fn from_array(array: A) -> Self { 73 | let array = make_array(array.into_data()); 74 | Self::from_array_ref(array) 75 | } 76 | 77 | /// Create a new Data from an [ArrayRef], inferring its data type automatically. 78 | pub fn from_array_ref(array: ArrayRef) -> Self { 79 | let field = Field::new("", array.data_type().clone(), true); 80 | Self::new(array, Arc::new(field)) 81 | } 82 | } 83 | 84 | impl From for Data { 85 | fn from(array: ArrayRef) -> Self { 86 | Self::from_array_ref(array) 87 | } 88 | } 89 | 90 | impl AsRef for Data { 91 | fn as_ref(&self) -> &ArrayRef { 92 | &self.array 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/datatype.rs: -------------------------------------------------------------------------------- 1 | // Allow struct fields to match Arrow representation, even when not currently used 2 | #![allow(dead_code)] 3 | 4 | use arrow_schema::{FieldRef, Fields, IntervalUnit, TimeUnit, UnionFields, UnionMode}; 5 | use std::sync::Arc; 6 | use wasm_bindgen::prelude::*; 7 | 8 | pub struct DataType(arrow_schema::DataType); 9 | 10 | /// Null type 11 | #[wasm_bindgen] 12 | pub struct Null; 13 | 14 | /// A boolean datatype representing the values `true` and `false`. 15 | #[wasm_bindgen] 16 | pub struct Boolean; 17 | 18 | /// A signed 8-bit integer. 19 | #[wasm_bindgen] 20 | pub struct Int8; 21 | 22 | /// A signed 16-bit integer. 23 | #[wasm_bindgen] 24 | pub struct Int16; 25 | 26 | /// A signed 32-bit integer. 27 | #[wasm_bindgen] 28 | pub struct Int32; 29 | 30 | /// A signed 64-bit integer. 31 | #[wasm_bindgen] 32 | pub struct Int64; 33 | 34 | /// An unsigned 8-bit integer. 35 | #[wasm_bindgen] 36 | pub struct UInt8; 37 | 38 | /// An unsigned 16-bit integer. 39 | #[wasm_bindgen] 40 | pub struct UInt16; 41 | 42 | /// An unsigned 32-bit integer. 43 | #[wasm_bindgen] 44 | pub struct UInt32; 45 | 46 | /// An unsigned 64-bit integer. 47 | #[wasm_bindgen] 48 | pub struct UInt64; 49 | 50 | /// A 16-bit floating point number. 51 | #[wasm_bindgen] 52 | pub struct Float16; 53 | 54 | /// A 32-bit floating point number. 55 | #[wasm_bindgen] 56 | pub struct Float32; 57 | 58 | /// A 64-bit floating point number. 59 | #[wasm_bindgen] 60 | pub struct Float64; 61 | 62 | /// A timestamp with an optional timezone. 63 | /// 64 | /// Time is measured as a Unix epoch, counting the seconds from 65 | /// 00:00:00.000 on 1 January 1970, excluding leap seconds, 66 | /// as a 64-bit integer. 67 | /// 68 | /// The time zone is a string indicating the name of a time zone, one of: 69 | /// 70 | /// * As used in the Olson time zone database (the "tz database" or 71 | /// "tzdata"), such as "America/New_York" 72 | /// * An absolute time zone offset of the form +XX:XX or -XX:XX, such as +07:30 73 | /// 74 | /// Timestamps with a non-empty timezone 75 | /// ------------------------------------ 76 | /// 77 | /// If a Timestamp column has a non-empty timezone value, its epoch is 78 | /// 1970-01-01 00:00:00 (January 1st 1970, midnight) in the *UTC* timezone 79 | /// (the Unix epoch), regardless of the Timestamp's own timezone. 80 | /// 81 | /// Therefore, timestamp values with a non-empty timezone correspond to 82 | /// physical points in time together with some additional information about 83 | /// how the data was obtained and/or how to display it (the timezone). 84 | /// 85 | /// For example, the timestamp value 0 with the timezone string "Europe/Paris" 86 | /// corresponds to "January 1st 1970, 00h00" in the UTC timezone, but the 87 | /// application may prefer to display it as "January 1st 1970, 01h00" in 88 | /// the Europe/Paris timezone (which is the same physical point in time). 89 | /// 90 | /// One consequence is that timestamp values with a non-empty timezone 91 | /// can be compared and ordered directly, since they all share the same 92 | /// well-known point of reference (the Unix epoch). 93 | /// 94 | /// Timestamps with an unset / empty timezone 95 | /// ----------------------------------------- 96 | /// 97 | /// If a Timestamp column has no timezone value, its epoch is 98 | /// 1970-01-01 00:00:00 (January 1st 1970, midnight) in an *unknown* timezone. 99 | /// 100 | /// Therefore, timestamp values without a timezone cannot be meaningfully 101 | /// interpreted as physical points in time, but only as calendar / clock 102 | /// indications ("wall clock time") in an unspecified timezone. 103 | /// 104 | /// For example, the timestamp value 0 with an empty timezone string 105 | /// corresponds to "January 1st 1970, 00h00" in an unknown timezone: there 106 | /// is not enough information to interpret it as a well-defined physical 107 | /// point in time. 108 | /// 109 | /// One consequence is that timestamp values without a timezone cannot 110 | /// be reliably compared or ordered, since they may have different points of 111 | /// reference. In particular, it is *not* possible to interpret an unset 112 | /// or empty timezone as the same as "UTC". 113 | /// 114 | /// Conversion between timezones 115 | /// ---------------------------- 116 | /// 117 | /// If a Timestamp column has a non-empty timezone, changing the timezone 118 | /// to a different non-empty value is a metadata-only operation: 119 | /// the timestamp values need not change as their point of reference remains 120 | /// the same (the Unix epoch). 121 | /// 122 | /// However, if a Timestamp column has no timezone value, changing it to a 123 | /// non-empty value requires to think about the desired semantics. 124 | /// One possibility is to assume that the original timestamp values are 125 | /// relative to the epoch of the timezone being set; timestamp values should 126 | /// then adjusted to the Unix epoch (for example, changing the timezone from 127 | /// empty to "Europe/Paris" would require converting the timestamp values 128 | /// from "Europe/Paris" to "UTC", which seems counter-intuitive but is 129 | /// nevertheless correct). 130 | #[wasm_bindgen] 131 | pub struct Timestamp(TimeUnit, Option>); 132 | 133 | impl Timestamp { 134 | pub fn new(unit: TimeUnit, tz: Option>) -> Self { 135 | Self(unit, tz) 136 | } 137 | } 138 | 139 | /// A 32-bit date representing the elapsed time since UNIX epoch (1970-01-01) 140 | /// in days (32 bits). 141 | #[wasm_bindgen] 142 | pub struct Date32; 143 | 144 | /// A 64-bit date representing the elapsed time since UNIX epoch (1970-01-01) 145 | /// in milliseconds (64 bits). Values are evenly divisible by 86400000. 146 | #[wasm_bindgen] 147 | pub struct Date64; 148 | 149 | /// A 32-bit time representing the elapsed time since midnight in the unit of `TimeUnit`. 150 | #[wasm_bindgen] 151 | pub struct Time32(TimeUnit); 152 | 153 | impl Time32 { 154 | pub fn new(unit: TimeUnit) -> Self { 155 | Self(unit) 156 | } 157 | } 158 | 159 | /// A 64-bit time representing the elapsed time since midnight in the unit of `TimeUnit`. 160 | #[wasm_bindgen] 161 | pub struct Time64(TimeUnit); 162 | 163 | impl Time64 { 164 | pub fn new(unit: TimeUnit) -> Self { 165 | Self(unit) 166 | } 167 | } 168 | 169 | /// Measure of elapsed time in either seconds, milliseconds, microseconds or nanoseconds. 170 | #[wasm_bindgen] 171 | pub struct Duration(TimeUnit); 172 | 173 | impl Duration { 174 | pub fn new(unit: TimeUnit) -> Self { 175 | Self(unit) 176 | } 177 | } 178 | 179 | /// A "calendar" interval which models types that don't necessarily 180 | /// have a precise duration without the context of a base timestamp (e.g. 181 | /// days can differ in length during day light savings time transitions). 182 | #[wasm_bindgen] 183 | pub struct Interval(IntervalUnit); 184 | 185 | impl Interval { 186 | pub fn new(unit: IntervalUnit) -> Self { 187 | Self(unit) 188 | } 189 | } 190 | 191 | /// Opaque binary data of variable length. 192 | /// 193 | /// A single Binary array can store up to [`i32::MAX`] bytes 194 | /// of binary data in total 195 | #[wasm_bindgen] 196 | pub struct Binary; 197 | 198 | /// Opaque binary data of fixed size. 199 | /// Enum parameter specifies the number of bytes per value. 200 | #[wasm_bindgen] 201 | pub struct FixedSizeBinary(i32); 202 | 203 | impl FixedSizeBinary { 204 | pub fn new(size: i32) -> Self { 205 | Self(size) 206 | } 207 | } 208 | 209 | /// Opaque binary data of variable length and 64-bit offsets. 210 | /// 211 | /// A single LargeBinary array can store up to [`i64::MAX`] bytes 212 | /// of binary data in total 213 | #[wasm_bindgen] 214 | pub struct LargeBinary; 215 | 216 | /// A variable-length string in Unicode with UTF-8 encoding 217 | /// 218 | /// A single Utf8 array can store up to [`i32::MAX`] bytes 219 | /// of string data in total 220 | #[wasm_bindgen] 221 | pub struct Utf8; 222 | 223 | /// A variable-length string in Unicode with UFT-8 encoding and 64-bit offsets. 224 | /// 225 | /// A single LargeUtf8 array can store up to [`i64::MAX`] bytes 226 | /// of string data in total 227 | #[wasm_bindgen] 228 | pub struct LargeUtf8; 229 | 230 | /// A list of some logical data type with variable length. 231 | /// 232 | /// A single List array can store up to [`i32::MAX`] elements in total 233 | #[wasm_bindgen] 234 | pub struct List(FieldRef); 235 | 236 | impl List { 237 | pub fn new(field: FieldRef) -> Self { 238 | Self(field) 239 | } 240 | } 241 | 242 | /// A list of some logical data type with fixed length. 243 | #[wasm_bindgen] 244 | pub struct FixedSizeList(FieldRef, i32); 245 | 246 | impl FixedSizeList { 247 | pub fn new(field: FieldRef, size: i32) -> Self { 248 | Self(field, size) 249 | } 250 | } 251 | 252 | /// A list of some logical data type with variable length and 64-bit offsets. 253 | /// 254 | /// A single LargeList array can store up to [`i64::MAX`] elements in total 255 | #[wasm_bindgen] 256 | pub struct LargeList(FieldRef); 257 | 258 | impl LargeList { 259 | pub fn new(field: FieldRef) -> Self { 260 | Self(field) 261 | } 262 | } 263 | 264 | /// A nested datatype that contains a number of sub-fields. 265 | #[wasm_bindgen] 266 | pub struct Struct(Fields); 267 | 268 | impl Struct { 269 | pub fn new(fields: Fields) -> Self { 270 | Self(fields) 271 | } 272 | } 273 | 274 | /// A nested datatype that can represent slots of differing types. Components: 275 | /// 276 | /// 1. [`UnionFields`] 277 | /// 2. The type of union (Sparse or Dense) 278 | #[wasm_bindgen] 279 | pub struct Union(UnionFields, UnionMode); 280 | 281 | impl Union { 282 | pub fn new(fields: UnionFields, mode: UnionMode) -> Self { 283 | Self(fields, mode) 284 | } 285 | } 286 | 287 | /// A dictionary encoded array (`key_type`, `value_type`), where 288 | /// each array element is an index of `key_type` into an 289 | /// associated dictionary of `value_type`. 290 | /// 291 | /// Dictionary arrays are used to store columns of `value_type` 292 | /// that contain many repeated values using less memory, but with 293 | /// a higher CPU overhead for some operations. 294 | /// 295 | /// This type mostly used to represent low cardinality string 296 | /// arrays or a limited set of primitive types as integers. 297 | #[wasm_bindgen] 298 | pub struct Dictionary(Box, Box); 299 | 300 | impl Dictionary { 301 | pub fn new( 302 | key_type: Box, 303 | value_type: Box, 304 | ) -> Self { 305 | Self(key_type, value_type) 306 | } 307 | } 308 | 309 | /// Exact 128-bit width decimal value with precision and scale 310 | /// 311 | /// * precision is the total number of digits 312 | /// * scale is the number of digits past the decimal 313 | /// 314 | /// For example the number 123.45 has precision 5 and scale 2. 315 | /// 316 | /// In certain situations, scale could be negative number. For 317 | /// negative scale, it is the number of padding 0 to the right 318 | /// of the digits. 319 | /// 320 | /// For example the number 12300 could be treated as a decimal 321 | /// has precision 3 and scale -2. 322 | #[wasm_bindgen] 323 | pub struct Decimal128(u8, i8); 324 | 325 | impl Decimal128 { 326 | pub fn new(precision: u8, scale: i8) -> Self { 327 | Self(precision, scale) 328 | } 329 | } 330 | 331 | /// Exact 256-bit width decimal value with precision and scale 332 | /// 333 | /// * precision is the total number of digits 334 | /// * scale is the number of digits past the decimal 335 | /// 336 | /// For example the number 123.45 has precision 5 and scale 2. 337 | /// 338 | /// In certain situations, scale could be negative number. For 339 | /// negative scale, it is the number of padding 0 to the right 340 | /// of the digits. 341 | /// 342 | /// For example the number 12300 could be treated as a decimal 343 | /// has precision 3 and scale -2. 344 | #[wasm_bindgen] 345 | pub struct Decimal256(u8, i8); 346 | 347 | impl Decimal256 { 348 | pub fn new(precision: u8, scale: i8) -> Self { 349 | Self(precision, scale) 350 | } 351 | } 352 | 353 | /// A Map is a logical nested type that is represented as 354 | /// 355 | /// `List>` 356 | /// 357 | /// The keys and values are each respectively contiguous. 358 | /// The key and value types are not constrained, but keys should be 359 | /// hashable and unique. 360 | /// Whether the keys are sorted can be set in the `bool` after the `Field`. 361 | /// 362 | /// In a field with Map type, the field has a child Struct field, which then 363 | /// has two children: key type and the second the value type. The names of the 364 | /// child fields may be respectively "entries", "key", and "value", but this is 365 | /// not enforced. 366 | #[wasm_bindgen] 367 | pub struct Map_(FieldRef, bool); 368 | 369 | impl Map_ { 370 | pub fn new(field: FieldRef, sorted: bool) -> Self { 371 | Self(field, sorted) 372 | } 373 | } 374 | 375 | /// A run-end encoding (REE) is a variation of run-length encoding (RLE). These 376 | /// encodings are well-suited for representing data containing sequences of the 377 | /// same value, called runs. Each run is represented as a value and an integer giving 378 | /// the index in the array where the run ends. 379 | /// 380 | /// A run-end encoded array has no buffers by itself, but has two child arrays. The 381 | /// first child array, called the run ends array, holds either 16, 32, or 64-bit 382 | /// signed integers. The actual values of each run are held in the second child array. 383 | /// 384 | /// These child arrays are prescribed the standard names of "run_ends" and "values" 385 | /// respectively. 386 | #[wasm_bindgen] 387 | pub struct RunEndEncoded(FieldRef, FieldRef); 388 | 389 | impl RunEndEncoded { 390 | pub fn new(run_ends: FieldRef, values: FieldRef) -> Self { 391 | Self(run_ends, values) 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use arrow_schema::ArrowError; 2 | use thiserror::Error; 3 | use wasm_bindgen::JsError; 4 | 5 | #[derive(Error, Debug)] 6 | pub enum ArrowWasmError { 7 | #[error(transparent)] 8 | ArrowError(Box), 9 | 10 | #[error("Internal error: `{0}`")] 11 | InternalError(String), 12 | } 13 | 14 | pub type Result = std::result::Result; 15 | pub type WasmResult = std::result::Result; 16 | 17 | impl From for ArrowWasmError { 18 | fn from(err: ArrowError) -> Self { 19 | Self::ArrowError(Box::new(err)) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ffi/chunked.rs: -------------------------------------------------------------------------------- 1 | use arrow_array::ffi; 2 | use wasm_bindgen::convert::IntoWasmAbi; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use crate::ffi::FFISchema; 6 | 7 | /// A representation of an Arrow C Stream in WebAssembly memory exposed as FFI-compatible 8 | /// structs through the Arrow C Data Interface. 9 | /// 10 | /// Unlike other Arrow implementations outside of JS, this always stores the "stream" fully 11 | /// materialized as a sequence of Arrow chunks. 12 | #[wasm_bindgen] 13 | pub struct FFIStream { 14 | pub(crate) field: FFISchema, 15 | pub(crate) arrays: Vec, 16 | } 17 | 18 | impl FFIStream { 19 | pub fn new(field: Box, arrays: Vec) -> Self { 20 | Self { 21 | field: FFISchema::new(field), 22 | arrays, 23 | } 24 | } 25 | } 26 | 27 | #[wasm_bindgen] 28 | impl FFIStream { 29 | /// Get the total number of elements in this stream 30 | #[wasm_bindgen(js_name = numArrays)] 31 | pub fn num_arrays(&self) -> usize { 32 | self.arrays.len() 33 | } 34 | 35 | /// Get the pointer to the ArrowSchema FFI struct 36 | #[wasm_bindgen(js_name = schemaAddr)] 37 | pub fn schema_addr(&self) -> *const ffi::FFI_ArrowSchema { 38 | self.field.addr() 39 | } 40 | 41 | /// Get the pointer to one ArrowArray FFI struct for a given chunk index and column index 42 | /// 43 | /// Access the pointer to one 44 | /// [`ArrowArray`](https://arrow.apache.org/docs/format/CDataInterface.html#structure-definitions) 45 | /// struct representing one of the internal `RecordBatch`es. This can be viewed or copied (without serialization) to an Arrow JS `RecordBatch` by 46 | /// using [`arrow-js-ffi`](https://github.com/kylebarron/arrow-js-ffi). You can access the 47 | /// [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Memory) 48 | /// instance by using {@linkcode wasmMemory}. 49 | /// 50 | /// **Example**: 51 | /// 52 | /// ```ts 53 | /// import * as arrow from "apache-arrow"; 54 | /// import { parseRecordBatch } from "arrow-js-ffi"; 55 | /// 56 | /// const wasmTable: FFITable = ... 57 | /// const wasmMemory: WebAssembly.Memory = wasmMemory(); 58 | /// 59 | /// const jsBatches: arrow.RecordBatch[] = [] 60 | /// for (let i = 0; i < wasmTable.numBatches(); i++) { 61 | /// // Pass `true` to copy arrays across the boundary instead of creating views. 62 | /// const jsRecordBatch = parseRecordBatch( 63 | /// wasmMemory.buffer, 64 | /// wasmTable.arrayAddr(i), 65 | /// wasmTable.schemaAddr(), 66 | /// true 67 | /// ); 68 | /// jsBatches.push(jsRecordBatch); 69 | /// } 70 | /// const jsTable = new arrow.Table(jsBatches); 71 | /// ``` 72 | /// 73 | /// @param chunk number The chunk index to use 74 | /// @returns number pointer to an ArrowArray FFI struct in Wasm memory 75 | #[wasm_bindgen(js_name = arrayAddr)] 76 | pub fn array_addr(&self, chunk: usize) -> *const ffi::FFI_ArrowArray { 77 | &self.arrays[chunk] as *const _ 78 | } 79 | 80 | #[wasm_bindgen(js_name = arrayAddrs)] 81 | pub fn array_addrs(&self) -> Vec { 82 | // wasm-bindgen doesn't allow a Vec<*const ffi::FFI_ArrowArray> so we cast to u32 83 | self.arrays 84 | .iter() 85 | .map(|array| (array as *const ffi::FFI_ArrowArray).into_abi()) 86 | .collect() 87 | } 88 | 89 | #[wasm_bindgen] 90 | pub fn drop(self) { 91 | drop(self.field); 92 | drop(self.arrays); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/ffi/data.rs: -------------------------------------------------------------------------------- 1 | use arrow_array::{ffi, Array, StructArray}; 2 | use arrow_schema::{ArrowError, Field}; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use crate::error::Result; 6 | use crate::ArrowWasmError; 7 | 8 | /// An Arrow array exported to FFI. 9 | /// 10 | /// Using [`arrow-js-ffi`](https://github.com/kylebarron/arrow-js-ffi), you can view or copy Arrow 11 | /// these objects to JavaScript. 12 | /// 13 | /// Note that this also includes an ArrowSchema C struct as well, so that extension type 14 | /// information can be maintained. 15 | // TODO: fix example 16 | // ```ts 17 | // import { parseField, parseVector } from "arrow-js-ffi"; 18 | // 19 | // // You need to access the geoarrow webassembly memory space. 20 | // // The way to do this is different per geoarrow bundle method. 21 | // const WASM_MEMORY: WebAssembly.Memory = geoarrow.__wasm.memory; 22 | // 23 | // // Say we have a point array from somewhere 24 | // const pointArray: geoarrow.PointArray = ...; 25 | // 26 | // // Export this existing point array to wasm. 27 | // const ffiArray = pointArray.toFfi(); 28 | // 29 | // // Parse an arrow-js field object from the pointer 30 | // const jsArrowField = parseField(WASM_MEMORY.buffer, ffiArray.field_addr()); 31 | // 32 | // // Parse an arrow-js vector from the pointer and parsed field 33 | // const jsPointVector = parseVector( 34 | // WASM_MEMORY.buffer, 35 | // ffiArray.array_addr(), 36 | // field.type 37 | // ); 38 | // ``` 39 | // 40 | /// ## Memory management 41 | /// 42 | /// Note that this array will not be released automatically. You need to manually call `.free()` to 43 | /// release memory. 44 | #[wasm_bindgen] 45 | pub struct FFIData { 46 | array: Box, 47 | field: Box, 48 | } 49 | 50 | impl FFIData { 51 | pub fn new(array: Box, field: Box) -> Self { 52 | Self { array, field } 53 | } 54 | 55 | /// Construct an [FFIData] from an Arrow array and optionally a field. 56 | /// 57 | /// In the Rust Arrow implementation, arrays do not store associated fields, so exporting an 58 | /// `Arc` to this [`FFIData`] will infer a "default field" for the given data type. 59 | /// This is not sufficient for some Arrow data, such as with extension types, where custom 60 | /// field metadata is required. 61 | pub fn from_arrow( 62 | array: &dyn Array, 63 | field: impl TryInto, 64 | ) -> Result { 65 | let ffi_field: arrow_array::ffi::FFI_ArrowSchema = field.try_into()?; 66 | let ffi_array = arrow_array::ffi::FFI_ArrowArray::new(&array.to_data()); 67 | 68 | Ok(Self { 69 | array: Box::new(ffi_array), 70 | field: Box::new(ffi_field), 71 | }) 72 | } 73 | } 74 | 75 | impl TryFrom<&dyn Array> for FFIData { 76 | type Error = crate::error::ArrowWasmError; 77 | 78 | fn try_from(value: &dyn Array) -> Result { 79 | let ffi_field = ffi::FFI_ArrowSchema::try_from(value.data_type())?; 80 | let ffi_array = ffi::FFI_ArrowArray::new(&value.to_data()); 81 | Ok(Self { 82 | field: Box::new(ffi_field), 83 | array: Box::new(ffi_array), 84 | }) 85 | } 86 | } 87 | 88 | impl TryFrom<&arrow_array::RecordBatch> for FFIData { 89 | type Error = ArrowWasmError; 90 | 91 | fn try_from(value: &arrow_array::RecordBatch) -> std::result::Result { 92 | let field = Field::new_struct("", value.schema_ref().fields().clone(), false); 93 | let data = StructArray::from(value.clone()); 94 | Self::from_arrow(&data, field) 95 | } 96 | } 97 | 98 | #[wasm_bindgen] 99 | impl FFIData { 100 | /// Access the pointer to the 101 | /// [`ArrowArray`](https://arrow.apache.org/docs/format/CDataInterface.html#structure-definitions) 102 | /// struct. This can be viewed or copied (without serialization) to an Arrow JS `RecordBatch` by 103 | /// using [`arrow-js-ffi`](https://github.com/kylebarron/arrow-js-ffi). You can access the 104 | /// [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Memory) 105 | /// instance by using {@linkcode wasmMemory}. 106 | /// 107 | /// **Example**: 108 | /// 109 | /// ```ts 110 | /// import { parseRecordBatch } from "arrow-js-ffi"; 111 | /// 112 | /// const wasmRecordBatch: FFIRecordBatch = ... 113 | /// const wasmMemory: WebAssembly.Memory = wasmMemory(); 114 | /// 115 | /// // Pass `true` to copy arrays across the boundary instead of creating views. 116 | /// const jsRecordBatch = parseRecordBatch( 117 | /// wasmMemory.buffer, 118 | /// wasmRecordBatch.arrayAddr(), 119 | /// wasmRecordBatch.schemaAddr(), 120 | /// true 121 | /// ); 122 | /// ``` 123 | #[wasm_bindgen(js_name = arrayAddr)] 124 | pub fn array_addr(&self) -> *const ffi::FFI_ArrowArray { 125 | self.array.as_ref() as *const _ 126 | } 127 | 128 | /// Access the pointer to the 129 | /// [`ArrowSchema`](https://arrow.apache.org/docs/format/CDataInterface.html#structure-definitions) 130 | /// struct. This can be viewed or copied (without serialization) to an Arrow JS `Field` by 131 | /// using [`arrow-js-ffi`](https://github.com/kylebarron/arrow-js-ffi). You can access the 132 | /// [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Memory) 133 | /// instance by using {@linkcode wasmMemory}. 134 | /// 135 | /// **Example**: 136 | /// 137 | /// ```ts 138 | /// import { parseRecordBatch } from "arrow-js-ffi"; 139 | /// 140 | /// const wasmRecordBatch: FFIRecordBatch = ... 141 | /// const wasmMemory: WebAssembly.Memory = wasmMemory(); 142 | /// 143 | /// // Pass `true` to copy arrays across the boundary instead of creating views. 144 | /// const jsRecordBatch = parseRecordBatch( 145 | /// wasmMemory.buffer, 146 | /// wasmRecordBatch.arrayAddr(), 147 | /// wasmRecordBatch.schemaAddr(), 148 | /// true 149 | /// ); 150 | /// ``` 151 | #[wasm_bindgen(js_name = schemaAddr)] 152 | pub fn schema_addr(&self) -> *const ffi::FFI_ArrowSchema { 153 | self.field.as_ref() as *const _ 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/ffi/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod chunked; 2 | pub mod data; 3 | pub mod schema; 4 | 5 | pub use chunked::FFIStream; 6 | pub use data::FFIData; 7 | pub use schema::FFISchema; 8 | -------------------------------------------------------------------------------- /src/ffi/schema.rs: -------------------------------------------------------------------------------- 1 | use arrow_array::ffi; 2 | use arrow_schema::ArrowError; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use crate::error::Result; 6 | 7 | #[wasm_bindgen] 8 | pub struct FFISchema(Box); 9 | 10 | impl FFISchema { 11 | pub fn new(schema: Box) -> Self { 12 | Self(schema) 13 | } 14 | 15 | /// Construct an [FFIData] from an Arrow array and optionally a field. 16 | /// 17 | /// In the Rust Arrow implementation, arrays do not store associated fields, so exporting an 18 | /// `Arc` to this [`FFIData`] will infer a "default field" for the given data type. 19 | /// This is not sufficient for some Arrow data, such as with extension types, where custom 20 | /// field metadata is required. 21 | pub fn from_arrow( 22 | field: impl TryInto, 23 | ) -> Result { 24 | let ffi_field: arrow_array::ffi::FFI_ArrowSchema = field.try_into()?; 25 | Ok(Self::new(Box::new(ffi_field))) 26 | } 27 | } 28 | 29 | #[wasm_bindgen] 30 | impl FFISchema { 31 | /// Access the pointer to the 32 | /// [`ArrowSchema`](https://arrow.apache.org/docs/format/CDataInterface.html#structure-definitions) 33 | /// struct. This can be viewed or copied (without serialization) to an Arrow JS `Field` by 34 | /// using [`arrow-js-ffi`](https://github.com/kylebarron/arrow-js-ffi). You can access the 35 | /// [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Memory) 36 | /// instance by using {@linkcode wasmMemory}. 37 | /// 38 | /// **Example**: 39 | /// 40 | /// ```ts 41 | /// import { parseRecordBatch } from "arrow-js-ffi"; 42 | /// 43 | /// const wasmRecordBatch: FFIRecordBatch = ... 44 | /// const wasmMemory: WebAssembly.Memory = wasmMemory(); 45 | /// 46 | /// // Pass `true` to copy arrays across the boundary instead of creating views. 47 | /// const jsRecordBatch = parseRecordBatch( 48 | /// wasmMemory.buffer, 49 | /// wasmRecordBatch.arrayAddr(), 50 | /// wasmRecordBatch.schemaAddr(), 51 | /// true 52 | /// ); 53 | /// ``` 54 | #[wasm_bindgen] 55 | pub fn addr(&self) -> *const ffi::FFI_ArrowSchema { 56 | self.0.as_ref() as *const _ 57 | } 58 | } 59 | 60 | impl TryFrom<&arrow_schema::Schema> for FFISchema { 61 | type Error = crate::error::ArrowWasmError; 62 | 63 | fn try_from(value: &arrow_schema::Schema) -> Result { 64 | Self::from_arrow(value) 65 | } 66 | } 67 | 68 | impl TryFrom<&arrow_schema::Field> for FFISchema { 69 | type Error = crate::error::ArrowWasmError; 70 | 71 | fn try_from(value: &arrow_schema::Field) -> Result { 72 | Self::from_arrow(value) 73 | } 74 | } 75 | 76 | #[cfg(feature = "schema")] 77 | impl TryFrom<&crate::Schema> for FFISchema { 78 | type Error = crate::error::ArrowWasmError; 79 | 80 | fn try_from(value: &crate::Schema) -> Result { 81 | Self::from_arrow(value.as_ref()) 82 | } 83 | } 84 | 85 | #[cfg(feature = "field")] 86 | impl TryFrom<&crate::Field> for FFISchema { 87 | type Error = crate::error::ArrowWasmError; 88 | 89 | fn try_from(value: &crate::Field) -> Result { 90 | Self::from_arrow(value.as_ref()) 91 | } 92 | } 93 | 94 | impl From> for FFISchema { 95 | fn from(value: Box) -> Self { 96 | Self(value) 97 | } 98 | } 99 | 100 | impl From for FFISchema { 101 | fn from(value: ffi::FFI_ArrowSchema) -> Self { 102 | Self(Box::new(value)) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/ffi/stream.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use arrow::array::Array; 4 | use arrow::ffi; 5 | use arrow::ffi_stream; 6 | use wasm_bindgen::prelude::*; 7 | 8 | use crate::error::{Result, WasmResult}; 9 | use crate::{Field, Schema}; 10 | 11 | 12 | #[wasm_bindgen] 13 | pub struct FFIArrowArrayStream(Box); 14 | 15 | impl FFIArrowArrayStream { 16 | pub fn new(stream: Box) -> Self { 17 | Self(stream) 18 | } 19 | } 20 | 21 | #[wasm_bindgen] 22 | impl FFIArrowArrayStream { 23 | #[wasm_bindgen] 24 | pub fn addr(&self) -> *const ffi_stream::FFI_ArrowArrayStream { 25 | self.0.as_ref() as *const _ 26 | } 27 | 28 | #[wasm_bindgen] 29 | pub fn get_schema(&mut self) -> WasmResult { 30 | let mut schema = ffi::FFI_ArrowSchema::empty(); 31 | 32 | let stream_ptr = self.0.as_mut() as *mut ffi_stream::FFI_ArrowArrayStream; 33 | let ret_code = unsafe { (*stream_ptr).get_schema.unwrap()(stream_ptr, &mut schema) }; 34 | 35 | if ret_code == 0 { 36 | Ok(schema.into()) 37 | } else { 38 | Err(JsError::new( 39 | "Cannot get schema from input stream. Error code: {ret_code:?}", 40 | )) 41 | } 42 | } 43 | 44 | #[wasm_bindgen] 45 | pub fn get_next(&mut self) -> WasmResult> { 46 | let mut array = ffi::FFI_ArrowArray::empty(); 47 | 48 | let stream_ptr = self.0.as_mut() as *mut ffi_stream::FFI_ArrowArrayStream; 49 | let ret_code = unsafe { (*stream_ptr).get_next.unwrap()(stream_ptr, &mut array) }; 50 | 51 | if ret_code == 0 { 52 | // The end of stream has been reached 53 | if array.is_released() { 54 | return Ok(None); 55 | } 56 | 57 | Ok(Some(array.into())) 58 | } else { 59 | Err(JsError::new( 60 | "Cannot get array from input stream. Error code: {ret_code:?}", 61 | )) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/field.rs: -------------------------------------------------------------------------------- 1 | use arrow_schema::DataType; 2 | use std::collections::HashMap; 3 | use std::sync::Arc; 4 | use wasm_bindgen::prelude::*; 5 | 6 | use crate::error::WasmResult; 7 | 8 | #[wasm_bindgen(typescript_custom_section)] 9 | const TS_FieldMetadata: &'static str = r#" 10 | export type FieldMetadata = Map; 11 | "#; 12 | 13 | #[wasm_bindgen] 14 | extern "C" { 15 | #[wasm_bindgen(typescript_type = "FieldMetadata")] 16 | pub type FieldMetadata; 17 | } 18 | 19 | #[wasm_bindgen] 20 | pub struct Field(pub(crate) arrow_schema::FieldRef); 21 | 22 | #[wasm_bindgen] 23 | impl Field { 24 | /// Export this field to an `FFISchema`` object, which can be read with arrow-js-ffi. 25 | #[wasm_bindgen(js_name = toFFI)] 26 | pub fn to_ffi(&self) -> WasmResult { 27 | Ok(crate::ffi::FFISchema::try_from(self)?) 28 | } 29 | 30 | /// Returns the `Field`'s name. 31 | #[wasm_bindgen] 32 | pub fn name(&self) -> String { 33 | self.0.name().clone() 34 | } 35 | 36 | /// Sets the name of this `Field` and returns a new object 37 | #[wasm_bindgen(js_name = withName)] 38 | pub fn with_name(&mut self, name: String) -> WasmResult { 39 | let field = self.0.as_ref().clone(); 40 | Ok(field.with_name(name).into()) 41 | } 42 | 43 | #[cfg(feature = "data_type")] 44 | #[wasm_bindgen(js_name = dataType)] 45 | pub fn data_type(&self) -> WasmResult { 46 | let dt = self.0.data_type(); 47 | let result = match dt { 48 | DataType::Null => crate::datatype::Null.into(), 49 | DataType::Boolean => crate::datatype::Boolean.into(), 50 | DataType::Int8 => crate::datatype::Int8.into(), 51 | DataType::Int16 => crate::datatype::Int16.into(), 52 | DataType::Int32 => crate::datatype::Int32.into(), 53 | DataType::Int64 => crate::datatype::Int64.into(), 54 | DataType::UInt8 => crate::datatype::UInt8.into(), 55 | DataType::UInt16 => crate::datatype::UInt16.into(), 56 | DataType::UInt32 => crate::datatype::UInt32.into(), 57 | DataType::UInt64 => crate::datatype::UInt64.into(), 58 | DataType::Float16 => crate::datatype::Float16.into(), 59 | DataType::Float32 => crate::datatype::Float32.into(), 60 | DataType::Float64 => crate::datatype::Float64.into(), 61 | DataType::Timestamp(unit, tz) => { 62 | crate::datatype::Timestamp::new(*unit, tz.clone()).into() 63 | } 64 | DataType::Date32 => crate::datatype::Date32.into(), 65 | DataType::Date64 => crate::datatype::Date64.into(), 66 | DataType::Time32(unit) => crate::datatype::Time32::new(*unit).into(), 67 | DataType::Time64(unit) => crate::datatype::Time64::new(*unit).into(), 68 | DataType::Duration(unit) => crate::datatype::Duration::new(*unit).into(), 69 | DataType::Interval(unit) => crate::datatype::Interval::new(*unit).into(), 70 | DataType::Binary => crate::datatype::Binary.into(), 71 | DataType::FixedSizeBinary(size) => crate::datatype::FixedSizeBinary::new(*size).into(), 72 | DataType::LargeBinary => crate::datatype::LargeBinary.into(), 73 | DataType::Utf8 => crate::datatype::Utf8.into(), 74 | DataType::LargeUtf8 => crate::datatype::LargeUtf8.into(), 75 | DataType::List(field) => crate::datatype::List::new(field.clone()).into(), 76 | DataType::FixedSizeList(field, size) => { 77 | crate::datatype::FixedSizeList::new(field.clone(), *size).into() 78 | } 79 | DataType::LargeList(field) => crate::datatype::LargeList::new(field.clone()).into(), 80 | DataType::Struct(fields) => crate::datatype::Struct::new(fields.clone()).into(), 81 | DataType::Union(fields, mode) => { 82 | crate::datatype::Union::new(fields.clone(), *mode).into() 83 | } 84 | DataType::Dictionary(key_type, value_type) => { 85 | crate::datatype::Dictionary::new(key_type.clone(), value_type.clone()).into() 86 | } 87 | DataType::Decimal128(precision, scale) => { 88 | crate::datatype::Decimal128::new(*precision, *scale).into() 89 | } 90 | DataType::Decimal256(precision, scale) => { 91 | crate::datatype::Decimal256::new(*precision, *scale).into() 92 | } 93 | DataType::Map(field, sorted) => { 94 | crate::datatype::Map_::new(field.clone(), *sorted).into() 95 | } 96 | DataType::RunEndEncoded(run_ends, values) => { 97 | crate::datatype::RunEndEncoded::new(run_ends.clone(), values.clone()).into() 98 | } 99 | dt => { 100 | return Err(JsError::new( 101 | format!("data type not yet supported: {}", dt).as_str(), 102 | )) 103 | } 104 | }; 105 | Ok(result) 106 | } 107 | 108 | /// Indicates whether this [`Field`] supports null values. 109 | #[wasm_bindgen(js_name = isNullable)] 110 | pub fn is_nullable(&self) -> bool { 111 | self.0.is_nullable() 112 | } 113 | 114 | #[wasm_bindgen] 115 | pub fn metadata(&self) -> WasmResult { 116 | Ok(serde_wasm_bindgen::to_value(self.0.metadata())?.into()) 117 | } 118 | 119 | /// Sets the metadata of this `Field` to be `metadata` and returns a new object 120 | #[wasm_bindgen(js_name = withMetadata)] 121 | pub fn with_metadata(&mut self, metadata: FieldMetadata) -> WasmResult { 122 | let metadata: HashMap = serde_wasm_bindgen::from_value(metadata.into())?; 123 | let field = self.0.as_ref().clone(); 124 | Ok(field.with_metadata(metadata).into()) 125 | } 126 | } 127 | 128 | impl From for Field { 129 | fn from(value: arrow_schema::Field) -> Self { 130 | Self(Arc::new(value)) 131 | } 132 | } 133 | 134 | impl From<&arrow_schema::Field> for Field { 135 | fn from(value: &arrow_schema::Field) -> Self { 136 | Self(Arc::new(value.clone())) 137 | } 138 | } 139 | 140 | impl From for Field { 141 | fn from(value: arrow_schema::FieldRef) -> Self { 142 | Self(value) 143 | } 144 | } 145 | 146 | impl From<&arrow_schema::FieldRef> for Field { 147 | fn from(value: &arrow_schema::FieldRef) -> Self { 148 | Self(value.clone()) 149 | } 150 | } 151 | 152 | impl AsRef for Field { 153 | fn as_ref(&self) -> &arrow_schema::Field { 154 | &self.0 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[cfg(feature = "read_arrow_js")] 4 | pub mod arrow_js; 5 | #[cfg(feature = "data")] 6 | pub mod data; 7 | #[cfg(feature = "data_type")] 8 | pub mod datatype; 9 | pub mod error; 10 | pub mod ffi; 11 | #[cfg(feature = "field")] 12 | pub mod field; 13 | #[cfg(feature = "record_batch")] 14 | pub mod record_batch; 15 | #[cfg(feature = "schema")] 16 | pub mod schema; 17 | #[cfg(feature = "table")] 18 | pub mod table; 19 | #[cfg(feature = "vector")] 20 | pub mod vector; 21 | 22 | pub use error::ArrowWasmError; 23 | #[cfg(feature = "field")] 24 | pub use field::Field; 25 | #[cfg(feature = "record_batch")] 26 | pub use record_batch::RecordBatch; 27 | #[cfg(feature = "schema")] 28 | pub use schema::Schema; 29 | #[cfg(feature = "table")] 30 | pub use table::Table; 31 | 32 | mod utils; 33 | 34 | #[wasm_bindgen(typescript_custom_section)] 35 | const TS_FunctionTable: &'static str = r#" 36 | export type FunctionTable = WebAssembly.Table; 37 | "#; 38 | 39 | #[wasm_bindgen(typescript_custom_section)] 40 | const TS_WasmMemory: &'static str = r#" 41 | export type Memory = WebAssembly.Memory; 42 | "#; 43 | 44 | #[wasm_bindgen] 45 | extern "C" { 46 | #[wasm_bindgen(typescript_type = "FunctionTable")] 47 | pub type FunctionTable; 48 | 49 | #[wasm_bindgen(typescript_type = "Memory")] 50 | pub type Memory; 51 | } 52 | 53 | /// Returns a handle to this wasm instance's `WebAssembly.Memory` 54 | #[wasm_bindgen(js_name = wasmMemory)] 55 | pub fn memory() -> Memory { 56 | wasm_bindgen::memory().into() 57 | } 58 | 59 | /// Returns a handle to this wasm instance's `WebAssembly.Table` which is the indirect function 60 | /// table used by Rust 61 | #[wasm_bindgen(js_name = _functionTable)] 62 | pub fn function_table() -> FunctionTable { 63 | wasm_bindgen::function_table().into() 64 | } 65 | -------------------------------------------------------------------------------- /src/record_batch.rs: -------------------------------------------------------------------------------- 1 | use crate::error::WasmResult; 2 | use crate::ffi::FFIData; 3 | use crate::ArrowWasmError; 4 | use wasm_bindgen::prelude::*; 5 | 6 | /// A group of columns of equal length in WebAssembly memory with an associated {@linkcode Schema}. 7 | #[wasm_bindgen] 8 | pub struct RecordBatch(arrow_array::RecordBatch); 9 | 10 | impl RecordBatch { 11 | pub fn new(batch: arrow_array::RecordBatch) -> Self { 12 | Self(batch) 13 | } 14 | 15 | pub fn into_inner(self) -> arrow_array::RecordBatch { 16 | self.0 17 | } 18 | } 19 | 20 | #[wasm_bindgen] 21 | impl RecordBatch { 22 | /// The number of rows in this RecordBatch. 23 | #[wasm_bindgen(getter, js_name = numRows)] 24 | pub fn num_rows(&self) -> usize { 25 | self.0.num_rows() 26 | } 27 | 28 | /// The number of columns in this RecordBatch. 29 | #[wasm_bindgen(getter, js_name = numColumns)] 30 | pub fn num_columns(&self) -> usize { 31 | self.0.num_columns() 32 | } 33 | 34 | /// The {@linkcode Schema} of this RecordBatch. 35 | #[cfg(feature = "schema")] 36 | #[wasm_bindgen(getter)] 37 | pub fn schema(&self) -> crate::Schema { 38 | crate::Schema::new(self.0.schema()) 39 | } 40 | 41 | /// Export this RecordBatch to FFI structs according to the Arrow C Data Interface. 42 | /// 43 | /// This method **does not consume** the RecordBatch, so you must remember to call {@linkcode 44 | /// RecordBatch.free} to release the resources. The underlying arrays are reference counted, so 45 | /// this method does not copy data, it only prevents the data from being released. 46 | #[wasm_bindgen(js_name = toFFI)] 47 | pub fn to_ffi(&self) -> WasmResult { 48 | Ok((&self.0).try_into()?) 49 | } 50 | 51 | /// Export this RecordBatch to FFI structs according to the Arrow C Data Interface. 52 | /// 53 | /// This method **does consume** the RecordBatch, so the original RecordBatch will be 54 | /// inaccessible after this call. You must still call {@linkcode FFIRecordBatch.free} after 55 | /// you've finished using the FFIRecordBatch. 56 | #[wasm_bindgen(js_name = intoFFI)] 57 | pub fn into_ffi(self) -> WasmResult { 58 | Ok((&self.0).try_into()?) 59 | } 60 | 61 | /// Consume this RecordBatch and convert to an Arrow IPC Stream buffer 62 | #[wasm_bindgen(js_name = intoIPCStream)] 63 | pub fn into_ipc_stream(self) -> WasmResult> { 64 | let table = crate::Table::new(self.0.schema(), vec![self.0]); 65 | table.into_ipc_stream() 66 | } 67 | 68 | /// Override the schema of this [`RecordBatch`] 69 | /// 70 | /// Returns an error if `schema` is not a superset of the current schema 71 | /// as determined by [`Schema::contains`] 72 | #[cfg(feature = "schema")] 73 | #[wasm_bindgen(js_name = withSchema)] 74 | pub fn with_schema(&self, schema: crate::Schema) -> WasmResult { 75 | Ok(self.0.clone().with_schema(schema.0)?.into()) 76 | } 77 | 78 | /// Return a new RecordBatch where each column is sliced 79 | /// according to `offset` and `length` 80 | #[wasm_bindgen] 81 | pub fn slice(&self, offset: usize, length: usize) -> RecordBatch { 82 | self.0.slice(offset, length).into() 83 | } 84 | 85 | /// Returns the total number of bytes of memory occupied physically by this batch. 86 | #[wasm_bindgen(js_name = getArrayMemorySize)] 87 | pub fn get_array_memory_size(&self) -> usize { 88 | self.0.get_array_memory_size() 89 | } 90 | } 91 | 92 | impl From for RecordBatch { 93 | fn from(value: arrow_array::RecordBatch) -> Self { 94 | Self(value) 95 | } 96 | } 97 | 98 | impl From for arrow_array::RecordBatch { 99 | fn from(value: RecordBatch) -> Self { 100 | value.0 101 | } 102 | } 103 | 104 | impl TryFrom for FFIData { 105 | type Error = ArrowWasmError; 106 | 107 | fn try_from(value: RecordBatch) -> Result { 108 | (&value.0).try_into() 109 | } 110 | } 111 | 112 | impl TryFrom<&RecordBatch> for FFIData { 113 | type Error = ArrowWasmError; 114 | 115 | fn try_from(value: &RecordBatch) -> Result { 116 | (&value.0).try_into() 117 | } 118 | } 119 | 120 | impl AsRef for RecordBatch { 121 | fn as_ref(&self) -> &arrow_array::RecordBatch { 122 | &self.0 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/schema.rs: -------------------------------------------------------------------------------- 1 | use arrow_ipc::writer::StreamWriter; 2 | use std::collections::HashMap; 3 | use std::sync::Arc; 4 | use wasm_bindgen::prelude::*; 5 | 6 | use crate::error::WasmResult; 7 | use crate::ffi::FFISchema; 8 | 9 | #[wasm_bindgen(typescript_custom_section)] 10 | const TS_SchemaMetadata: &'static str = r#" 11 | export type SchemaMetadata = Map; 12 | "#; 13 | 14 | #[wasm_bindgen] 15 | extern "C" { 16 | #[wasm_bindgen(typescript_type = "SchemaMetadata")] 17 | pub type SchemaMetadata; 18 | } 19 | 20 | /// A named collection of types that defines the column names and types in a RecordBatch or Table 21 | /// data structure. 22 | /// 23 | /// A Schema can also contain extra user-defined metadata either at the Table or Column level. 24 | /// Column-level metadata is often used to define [extension 25 | /// types](https://arrow.apache.org/docs/format/Columnar.html#extension-types). 26 | #[wasm_bindgen] 27 | pub struct Schema(pub(crate) arrow_schema::SchemaRef); 28 | 29 | #[wasm_bindgen] 30 | impl Schema { 31 | /// Export this schema to an FFISchema object, which can be read with arrow-js-ffi. 32 | /// 33 | /// This method **does not consume** the Schema, so you must remember to call {@linkcode 34 | /// Schema.free} to release the resources. The underlying arrays are reference counted, so 35 | /// this method does not copy data, it only prevents the data from being released. 36 | #[wasm_bindgen(js_name = toFFI)] 37 | pub fn to_ffi(&self) -> WasmResult { 38 | Ok(FFISchema::from_arrow(self.0.as_ref())?) 39 | } 40 | 41 | /// Export this Table to FFI structs according to the Arrow C Data Interface. 42 | /// 43 | /// This method **does consume** the Table, so the original Table will be 44 | /// inaccessible after this call. You must still call {@linkcode FFITable.free} after 45 | /// you've finished using the FFITable. 46 | #[wasm_bindgen(js_name = intoFFI)] 47 | pub fn into_ffi(self) -> WasmResult { 48 | Ok(FFISchema::from_arrow(self.0.as_ref())?) 49 | } 50 | 51 | /// Consume this schema and convert to an Arrow IPC Stream buffer 52 | #[wasm_bindgen(js_name = intoIPCStream)] 53 | pub fn into_ipc_stream(self) -> WasmResult> { 54 | let mut output_file = Vec::new(); 55 | 56 | { 57 | let mut writer = StreamWriter::try_new(&mut output_file, &self.0)?; 58 | 59 | writer.finish()?; 60 | } 61 | 62 | // Note that this returns output_file directly instead of using 63 | // writer.into_inner().to_vec() as the latter seems likely to incur an extra copy of the 64 | // vec 65 | Ok(output_file) 66 | } 67 | 68 | /// Returns an immutable reference of a specific [`Field`] instance selected using an 69 | /// offset within the internal `fields` vector. 70 | #[cfg(feature = "field")] 71 | #[wasm_bindgen] 72 | pub fn field(&self, i: usize) -> crate::Field { 73 | (self.0.fields()[i].clone()).into() 74 | } 75 | 76 | /// Returns an immutable reference of a specific [`Field`] instance selected by name. 77 | #[cfg(feature = "field")] 78 | #[wasm_bindgen(js_name = fieldWithName)] 79 | pub fn field_with_name(&self, name: &str) -> WasmResult { 80 | let field = self.0.field_with_name(name)?; 81 | Ok(field.clone().into()) 82 | } 83 | 84 | /// Sets the metadata of this `Schema` to be `metadata` and returns a new object 85 | #[wasm_bindgen(js_name = withMetadata)] 86 | pub fn with_metadata(&mut self, metadata: SchemaMetadata) -> WasmResult { 87 | let metadata: HashMap = serde_wasm_bindgen::from_value(metadata.into())?; 88 | let field = self.0.as_ref().clone(); 89 | Ok(field.with_metadata(metadata).into()) 90 | } 91 | 92 | /// Find the index of the column with the given name. 93 | #[wasm_bindgen(js_name = indexOf)] 94 | pub fn index_of(&mut self, name: &str) -> WasmResult { 95 | Ok(self.0.index_of(name)?) 96 | } 97 | 98 | /// Returns an immutable reference to the Map of custom metadata key-value pairs. 99 | #[wasm_bindgen] 100 | pub fn metadata(&self) -> WasmResult { 101 | Ok(serde_wasm_bindgen::to_value(self.0.metadata())?.into()) 102 | } 103 | } 104 | 105 | impl Schema { 106 | pub fn new(schema: arrow_schema::SchemaRef) -> Self { 107 | Self(schema) 108 | } 109 | 110 | pub fn into_inner(self) -> arrow_schema::SchemaRef { 111 | self.0 112 | } 113 | } 114 | 115 | impl From for Schema { 116 | fn from(value: arrow_schema::Schema) -> Self { 117 | Self(Arc::new(value)) 118 | } 119 | } 120 | 121 | impl From for Schema { 122 | fn from(value: arrow_schema::SchemaRef) -> Self { 123 | Self(value) 124 | } 125 | } 126 | 127 | impl From for arrow_schema::SchemaRef { 128 | fn from(value: Schema) -> Self { 129 | value.0 130 | } 131 | } 132 | 133 | impl AsRef for Schema { 134 | fn as_ref(&self) -> &arrow_schema::Schema { 135 | &self.0 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/table.rs: -------------------------------------------------------------------------------- 1 | use crate::error::WasmResult; 2 | use crate::ffi::{FFISchema, FFIStream}; 3 | use crate::ArrowWasmError; 4 | use arrow_array::ffi; 5 | use arrow_array::{Array, StructArray}; 6 | use arrow_ipc::reader::StreamReader; 7 | use arrow_ipc::writer::StreamWriter; 8 | use std::io::Cursor; 9 | use wasm_bindgen::prelude::*; 10 | 11 | /// A Table in WebAssembly memory conforming to the Apache Arrow spec. 12 | /// 13 | /// A Table consists of one or more {@linkcode RecordBatch} objects plus a {@linkcode Schema} that 14 | /// each RecordBatch conforms to. 15 | #[derive(Debug)] 16 | #[wasm_bindgen] 17 | pub struct Table { 18 | schema: arrow_schema::SchemaRef, 19 | batches: Vec, 20 | } 21 | 22 | impl Table { 23 | /// Creates a new Table. 24 | /// 25 | /// # Alternatives 26 | /// 27 | /// If you're creating a function that takes in a generic Javascript arrow 28 | /// table, use [JSTable](crate::arrow_js::table::JSTable) and [Table::from_js](Table::from_js). 29 | /// 30 | /// ``` 31 | /// use wasm_bindgen::prelude::*; 32 | /// use arrow_wasm::{Table, arrow_js::table::JSTable, error::WasmResult}; 33 | /// 34 | /// #[wasm_bindgen] 35 | /// pub fn convert(table: &JSTable) -> WasmResult<()> { 36 | /// let table = Table::from_js(table)?; 37 | /// // Do something with the table 38 | /// Ok(()) 39 | /// } 40 | /// ``` 41 | pub fn new(schema: arrow_schema::SchemaRef, batches: Vec) -> Self { 42 | Self { schema, batches } 43 | } 44 | 45 | /// Consume this table and return its components 46 | pub fn into_inner(self) -> (arrow_schema::SchemaRef, Vec) { 47 | (self.schema, self.batches) 48 | } 49 | } 50 | 51 | #[wasm_bindgen] 52 | impl Table { 53 | /// Access the Table's {@linkcode Schema}. 54 | #[cfg(feature = "schema")] 55 | #[wasm_bindgen(getter)] 56 | pub fn schema(&self) -> crate::Schema { 57 | crate::Schema::new(self.schema.clone()) 58 | } 59 | 60 | /// Access a RecordBatch from the Table by index. 61 | /// 62 | /// @param index The positional index of the RecordBatch to retrieve. 63 | /// @returns a RecordBatch or `null` if out of range. 64 | #[cfg(feature = "record_batch")] 65 | #[wasm_bindgen(js_name = recordBatch)] 66 | pub fn record_batch(&self, index: usize) -> Option { 67 | let batch = self.batches.get(index)?; 68 | Some(crate::RecordBatch::new(batch.clone())) 69 | } 70 | 71 | #[cfg(feature = "record_batch")] 72 | #[wasm_bindgen(js_name = recordBatches)] 73 | pub fn record_batches(&self) -> Vec { 74 | self.batches 75 | .iter() 76 | .map(|batch| crate::RecordBatch::new(batch.clone())) 77 | .collect() 78 | } 79 | 80 | /// The number of batches in the Table 81 | #[wasm_bindgen(getter, js_name = numBatches)] 82 | pub fn num_batches(&self) -> usize { 83 | self.batches.len() 84 | } 85 | 86 | /// Export this Table to FFI structs according to the Arrow C Data Interface. 87 | /// 88 | /// This method **does not consume** the Table, so you must remember to call {@linkcode 89 | /// Table.free} to release the resources. The underlying arrays are reference counted, so 90 | /// this method does not copy data, it only prevents the data from being released. 91 | #[wasm_bindgen(js_name = toFFI)] 92 | pub fn to_ffi(&self) -> WasmResult { 93 | Ok(self.try_into()?) 94 | } 95 | 96 | /// Export this Table to FFI structs according to the Arrow C Data Interface. 97 | /// 98 | /// This method **does consume** the Table, so the original Table will be 99 | /// inaccessible after this call. You must still call {@linkcode FFITable.free} after 100 | /// you've finished using the FFITable. 101 | #[wasm_bindgen(js_name = intoFFI)] 102 | pub fn into_ffi(self) -> WasmResult { 103 | Ok((&self).try_into()?) 104 | } 105 | 106 | /// Consume this table and convert to an Arrow IPC Stream buffer 107 | #[wasm_bindgen(js_name = intoIPCStream)] 108 | pub fn into_ipc_stream(self) -> WasmResult> { 109 | let mut output_file = Vec::new(); 110 | 111 | { 112 | let mut writer = StreamWriter::try_new(&mut output_file, &self.schema)?; 113 | 114 | // Iterate over record batches, writing them to IPC stream 115 | for chunk in self.batches { 116 | writer.write(&chunk)?; 117 | } 118 | writer.finish()?; 119 | } 120 | 121 | // Note that this returns output_file directly instead of using 122 | // writer.into_inner().to_vec() as the latter seems likely to incur an extra copy of the 123 | // vec 124 | Ok(output_file) 125 | } 126 | 127 | /// Create a table from an Arrow IPC Stream buffer 128 | #[wasm_bindgen(js_name = fromIPCStream)] 129 | pub fn from_ipc_stream(buf: &[u8]) -> WasmResult
{ 130 | let input_file = Cursor::new(buf); 131 | let arrow_ipc_reader = StreamReader::try_new(input_file, None)?; 132 | let schema = arrow_ipc_reader.schema(); 133 | 134 | let mut batches = vec![]; 135 | for maybe_chunk in arrow_ipc_reader { 136 | let chunk = maybe_chunk?; 137 | batches.push(chunk); 138 | } 139 | 140 | Ok(Self::new(schema, batches)) 141 | } 142 | 143 | /// Returns the total number of bytes of memory occupied physically by all batches in this 144 | /// table. 145 | #[wasm_bindgen(js_name = getArrayMemorySize)] 146 | pub fn get_array_memory_size(&self) -> usize { 147 | self.batches 148 | .iter() 149 | .fold(0, |sum, batch| sum + batch.get_array_memory_size()) 150 | } 151 | } 152 | 153 | impl TryFrom<&Table> for FFIStream { 154 | type Error = ArrowWasmError; 155 | 156 | fn try_from(value: &Table) -> Result { 157 | let schema = FFISchema::from_arrow(value.schema.as_ref())?; 158 | 159 | let mut ffi_batches = Vec::with_capacity(value.num_batches()); 160 | for batch in value.batches.iter() { 161 | ffi_batches.push(ffi::FFI_ArrowArray::new( 162 | &StructArray::from(batch.clone()).into_data(), 163 | )); 164 | } 165 | 166 | Ok(Self { 167 | field: schema, 168 | arrays: ffi_batches, 169 | }) 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "debug")] 2 | use wasm_bindgen::prelude::*; 3 | 4 | /// Call this function at least once during initialization to get better error 5 | // messages if the underlying Rust code ever panics (creates uncaught errors). 6 | #[cfg(feature = "debug")] 7 | #[wasm_bindgen(js_name = setPanicHook)] 8 | pub fn set_panic_hook() { 9 | // When the `console_error_panic_hook` feature is enabled, we can call the 10 | // `set_panic_hook` function at least once during initialization, and then 11 | // we will get better error messages if our code ever panics. 12 | // 13 | // For more details see 14 | // https://github.com/rustwasm/console_error_panic_hook#readme 15 | console_error_panic_hook::set_once(); 16 | } 17 | -------------------------------------------------------------------------------- /src/vector.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use arrow_array::ArrayRef; 4 | use arrow_schema::{ArrowError, DataType, Field, FieldRef}; 5 | use wasm_bindgen::prelude::*; 6 | 7 | use crate::error::Result; 8 | use crate::ArrowWasmError; 9 | 10 | #[wasm_bindgen] 11 | pub struct Vector { 12 | chunks: Vec, 13 | field: FieldRef, 14 | } 15 | 16 | impl Vector { 17 | pub fn try_new(chunks: Vec, field: FieldRef) -> Result { 18 | if !chunks 19 | .iter() 20 | .all(|chunk| chunk.data_type().equals_datatype(field.data_type())) 21 | { 22 | return Err(ArrowWasmError::InternalError( 23 | "All chunks must have same data type".to_string(), 24 | )); 25 | } 26 | Ok(Self { chunks, field }) 27 | } 28 | 29 | pub fn data_type(&self) -> &DataType { 30 | self.field.data_type() 31 | } 32 | 33 | /// Create a new PyChunkedArray from a vec of [ArrayRef]s, inferring their data type 34 | /// automatically. 35 | pub fn from_array_refs(chunks: Vec) -> Result { 36 | if chunks.is_empty() { 37 | return Err(ArrowError::SchemaError( 38 | "Cannot infer data type from empty Vec".to_string(), 39 | ) 40 | .into()); 41 | } 42 | 43 | if !chunks 44 | .windows(2) 45 | .all(|w| w[0].data_type() == w[1].data_type()) 46 | { 47 | return Err(ArrowError::SchemaError("Mismatched data types".to_string()).into()); 48 | } 49 | 50 | let field = Field::new("", chunks.first().unwrap().data_type().clone(), true); 51 | Self::try_new(chunks, Arc::new(field)) 52 | } 53 | } 54 | 55 | impl TryFrom> for Vector { 56 | type Error = ArrowWasmError; 57 | 58 | fn try_from(value: Vec) -> Result { 59 | Self::from_array_refs(value) 60 | } 61 | } 62 | 63 | impl AsRef<[ArrayRef]> for Vector { 64 | fn as_ref(&self) -> &[ArrayRef] { 65 | &self.chunks 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tsconfig.docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["pkg/**/*.d.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arrow-wasm", 3 | "cleanOutputDir": true, 4 | "darkHighlightTheme": "github-dark", 5 | "entryPoints": [ 6 | "pkg/node/arrow_wasm.d.ts", 7 | "pkg/bundler/arrow_wasm.d.ts", 8 | "pkg/esm/arrow_wasm.d.ts", 9 | ], 10 | "lightHighlightTheme": "github-light", 11 | "tsconfig": "tsconfig.docs.json", 12 | "out": "docs_build", 13 | "excludePrivate": true, 14 | "excludeProtected": true, 15 | "excludeExternals": true, 16 | "includeVersion": true 17 | } 18 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 6 6 | cacheKey: 8 7 | 8 | "@75lb/deep-merge@npm:^1.1.1": 9 | version: 1.1.1 10 | resolution: "@75lb/deep-merge@npm:1.1.1" 11 | dependencies: 12 | lodash.assignwith: ^4.2.0 13 | typical: ^7.1.1 14 | checksum: fd9063488d854bc5d2e1636426a51d7864d0d32d2d82c5b01a40e89466088680f6e2623345fb46782de438088b6d3f029b0eea6d79a7807e0000b365f6b8142b 15 | languageName: node 16 | linkType: hard 17 | 18 | "@swc/helpers@npm:^0.5.2": 19 | version: 0.5.3 20 | resolution: "@swc/helpers@npm:0.5.3" 21 | dependencies: 22 | tslib: ^2.4.0 23 | checksum: 61c3f7ccd47fc70ad91437df88be6b458cdc11e311cb331288827d7c50befffc72aa18fe913ec2a9e70fbf44e4b818bed38bfd7c329d689e1ff3c198d084cd02 24 | languageName: node 25 | linkType: hard 26 | 27 | "@types/command-line-args@npm:^5.2.1": 28 | version: 5.2.3 29 | resolution: "@types/command-line-args@npm:5.2.3" 30 | checksum: 3d90db5b4bbaabd049654a0d12fa378989ab0d76a0f98d4c606761b5a08ce76458df0f9bb175219e187b4cd57e285e6f836d23e86b2c3d997820854cc3ed9121 31 | languageName: node 32 | linkType: hard 33 | 34 | "@types/command-line-usage@npm:^5.0.2": 35 | version: 5.0.4 36 | resolution: "@types/command-line-usage@npm:5.0.4" 37 | checksum: 7173c356ca8c9507feeeda8e660c52498929556e90be0cf2d09d35270c597481121cd0f006a74167c5577feebfbc75b648c0f8f01b8f06ce30bde9fe30d5ba40 38 | languageName: node 39 | linkType: hard 40 | 41 | "@types/node@npm:^20.6.0": 42 | version: 20.11.6 43 | resolution: "@types/node@npm:20.11.6" 44 | dependencies: 45 | undici-types: ~5.26.4 46 | checksum: 54b3739f42d9c2266fd724d8ecbf50bc64eb0563343b65a6ea874a51a7fc8bb4793bf3a1b2222e40e3b7bd62cf5af5609899bf1a3de8b69748dcac65e63e8bdc 47 | languageName: node 48 | linkType: hard 49 | 50 | "ansi-sequence-parser@npm:^1.1.0": 51 | version: 1.1.1 52 | resolution: "ansi-sequence-parser@npm:1.1.1" 53 | checksum: ead5b15c596e8e85ca02951a844366c6776769dcc9fd1bd3a0db11bb21364554822c6a439877fb599e7e1ffa0b5f039f1e5501423950457f3dcb2f480c30b188 54 | languageName: node 55 | linkType: hard 56 | 57 | "ansi-styles@npm:^4.1.0": 58 | version: 4.3.0 59 | resolution: "ansi-styles@npm:4.3.0" 60 | dependencies: 61 | color-convert: ^2.0.1 62 | checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 63 | languageName: node 64 | linkType: hard 65 | 66 | "apache-arrow@npm:^15.0.0": 67 | version: 15.0.0 68 | resolution: "apache-arrow@npm:15.0.0" 69 | dependencies: 70 | "@swc/helpers": ^0.5.2 71 | "@types/command-line-args": ^5.2.1 72 | "@types/command-line-usage": ^5.0.2 73 | "@types/node": ^20.6.0 74 | command-line-args: ^5.2.1 75 | command-line-usage: ^7.0.1 76 | flatbuffers: ^23.5.26 77 | json-bignum: ^0.0.3 78 | tslib: ^2.6.2 79 | bin: 80 | arrow2csv: bin/arrow2csv.cjs 81 | checksum: a7c4c365495798a320d693a150e8fdf978622be835dfa4722789e5ee95a3eff28c114db19faf4e79a744ee01e4544e0cd175dc07b55fc5375d103ff40949bd7a 82 | languageName: node 83 | linkType: hard 84 | 85 | "array-back@npm:^3.0.1, array-back@npm:^3.1.0": 86 | version: 3.1.0 87 | resolution: "array-back@npm:3.1.0" 88 | checksum: 7205004fcd0f9edd926db921af901b083094608d5b265738d0290092f9822f73accb468e677db74c7c94ef432d39e5ed75a7b1786701e182efb25bbba9734209 89 | languageName: node 90 | linkType: hard 91 | 92 | "array-back@npm:^6.2.2": 93 | version: 6.2.2 94 | resolution: "array-back@npm:6.2.2" 95 | checksum: baae1e3a1687300a307d3bdf09715f6415e1099b5729d3d8e397309fb1e43d90b939d694602892172aaca7e0aeed38da89d04aa4951637d31c2a21350809e003 96 | languageName: node 97 | linkType: hard 98 | 99 | "array-union@npm:^1.0.1": 100 | version: 1.0.2 101 | resolution: "array-union@npm:1.0.2" 102 | dependencies: 103 | array-uniq: ^1.0.1 104 | checksum: 82cec6421b6e6766556c484835a6d476a873f1b71cace5ab2b4f1b15b1e3162dc4da0d16f7a2b04d4aec18146c6638fe8f661340b31ba8e469fd811a1b45dc8d 105 | languageName: node 106 | linkType: hard 107 | 108 | "array-uniq@npm:^1.0.1": 109 | version: 1.0.3 110 | resolution: "array-uniq@npm:1.0.3" 111 | checksum: 1625f06b093d8bf279b81adfec6e72951c0857d65b5e3f65f053fffe9f9dd61c2fc52cff57e38a4700817e7e3f01a4faa433d505ea9e33cdae4514c334e0bf9e 112 | languageName: node 113 | linkType: hard 114 | 115 | "arrow-wasm@workspace:.": 116 | version: 0.0.0-use.local 117 | resolution: "arrow-wasm@workspace:." 118 | dependencies: 119 | apache-arrow: ^15.0.0 120 | gh-pages: ^6.0.0 121 | typedoc: ^0.25.1 122 | typescript: ^5.2.2 123 | languageName: unknown 124 | linkType: soft 125 | 126 | "async@npm:^3.2.4": 127 | version: 3.2.5 128 | resolution: "async@npm:3.2.5" 129 | checksum: 5ec77f1312301dee02d62140a6b1f7ee0edd2a0f983b6fd2b0849b969f245225b990b47b8243e7b9ad16451a53e7f68e753700385b706198ced888beedba3af4 130 | languageName: node 131 | linkType: hard 132 | 133 | "balanced-match@npm:^1.0.0": 134 | version: 1.0.2 135 | resolution: "balanced-match@npm:1.0.2" 136 | checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 137 | languageName: node 138 | linkType: hard 139 | 140 | "brace-expansion@npm:^1.1.7": 141 | version: 1.1.11 142 | resolution: "brace-expansion@npm:1.1.11" 143 | dependencies: 144 | balanced-match: ^1.0.0 145 | concat-map: 0.0.1 146 | checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 147 | languageName: node 148 | linkType: hard 149 | 150 | "brace-expansion@npm:^2.0.1": 151 | version: 2.0.1 152 | resolution: "brace-expansion@npm:2.0.1" 153 | dependencies: 154 | balanced-match: ^1.0.0 155 | checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 156 | languageName: node 157 | linkType: hard 158 | 159 | "chalk-template@npm:^0.4.0": 160 | version: 0.4.0 161 | resolution: "chalk-template@npm:0.4.0" 162 | dependencies: 163 | chalk: ^4.1.2 164 | checksum: 6c706802a79a7963cbce18f022b046fe86e438a67843151868852f80ea7346e975a6a9749991601e7e5d3b6a6c4852a04c53dc966a9a3d04031bd0e0ed53c819 165 | languageName: node 166 | linkType: hard 167 | 168 | "chalk@npm:^4.1.2": 169 | version: 4.1.2 170 | resolution: "chalk@npm:4.1.2" 171 | dependencies: 172 | ansi-styles: ^4.1.0 173 | supports-color: ^7.1.0 174 | checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc 175 | languageName: node 176 | linkType: hard 177 | 178 | "color-convert@npm:^2.0.1": 179 | version: 2.0.1 180 | resolution: "color-convert@npm:2.0.1" 181 | dependencies: 182 | color-name: ~1.1.4 183 | checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 184 | languageName: node 185 | linkType: hard 186 | 187 | "color-name@npm:~1.1.4": 188 | version: 1.1.4 189 | resolution: "color-name@npm:1.1.4" 190 | checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 191 | languageName: node 192 | linkType: hard 193 | 194 | "command-line-args@npm:^5.2.1": 195 | version: 5.2.1 196 | resolution: "command-line-args@npm:5.2.1" 197 | dependencies: 198 | array-back: ^3.1.0 199 | find-replace: ^3.0.0 200 | lodash.camelcase: ^4.3.0 201 | typical: ^4.0.0 202 | checksum: e759519087be3cf2e86af8b9a97d3058b4910cd11ee852495be881a067b72891f6a32718fb685ee6d41531ab76b2b7bfb6602f79f882cd4b7587ff1e827982c7 203 | languageName: node 204 | linkType: hard 205 | 206 | "command-line-usage@npm:^7.0.0, command-line-usage@npm:^7.0.1": 207 | version: 7.0.1 208 | resolution: "command-line-usage@npm:7.0.1" 209 | dependencies: 210 | array-back: ^6.2.2 211 | chalk-template: ^0.4.0 212 | table-layout: ^3.0.0 213 | typical: ^7.1.1 214 | checksum: ac78ad6b83b9622bb111ae8e82205bde1d2da74df237fdd0bd7d98eda3592c8933ec600818b0b028b2313ddca638b1b60f0780dd9457ad4a0384b17156641f79 215 | languageName: node 216 | linkType: hard 217 | 218 | "commander@npm:^11.0.0": 219 | version: 11.1.0 220 | resolution: "commander@npm:11.1.0" 221 | checksum: fd1a8557c6b5b622c89ecdfde703242ab7db3b628ea5d1755784c79b8e7cb0d74d65b4a262289b533359cd58e1bfc0bf50245dfbcd2954682a6f367c828b79ef 222 | languageName: node 223 | linkType: hard 224 | 225 | "commondir@npm:^1.0.1": 226 | version: 1.0.1 227 | resolution: "commondir@npm:1.0.1" 228 | checksum: 59715f2fc456a73f68826285718503340b9f0dd89bfffc42749906c5cf3d4277ef11ef1cca0350d0e79204f00f1f6d83851ececc9095dc88512a697ac0b9bdcb 229 | languageName: node 230 | linkType: hard 231 | 232 | "concat-map@npm:0.0.1": 233 | version: 0.0.1 234 | resolution: "concat-map@npm:0.0.1" 235 | checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af 236 | languageName: node 237 | linkType: hard 238 | 239 | "email-addresses@npm:^5.0.0": 240 | version: 5.0.0 241 | resolution: "email-addresses@npm:5.0.0" 242 | checksum: e58a510e9caf105313025e1c81488d5391c6404f0bbd7874e8e36a4c14d1ced02ff271748146c13edfa3bd9ce9b25f1194f5369971d77087325f37ab193129bb 243 | languageName: node 244 | linkType: hard 245 | 246 | "escape-string-regexp@npm:^1.0.2": 247 | version: 1.0.5 248 | resolution: "escape-string-regexp@npm:1.0.5" 249 | checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 250 | languageName: node 251 | linkType: hard 252 | 253 | "filename-reserved-regex@npm:^2.0.0": 254 | version: 2.0.0 255 | resolution: "filename-reserved-regex@npm:2.0.0" 256 | checksum: 323a0020fd7f243238ffccab9d728cbc5f3a13c84b2c10e01efb09b8324561d7a51776be76f36603c734d4f69145c39a5d12492bf6142a28b50d7f90bd6190bc 257 | languageName: node 258 | linkType: hard 259 | 260 | "filenamify@npm:^4.3.0": 261 | version: 4.3.0 262 | resolution: "filenamify@npm:4.3.0" 263 | dependencies: 264 | filename-reserved-regex: ^2.0.0 265 | strip-outer: ^1.0.1 266 | trim-repeated: ^1.0.0 267 | checksum: 5b71a7ff8e958c8621957e6fbf7872024126d3b5da50f59b1634af3343ba1a69d4cc15cfe4ca4bbfa7c959ad4d98614ee51e6f1d9fa7326eef8ceda2da8cd74e 268 | languageName: node 269 | linkType: hard 270 | 271 | "find-cache-dir@npm:^3.3.1": 272 | version: 3.3.2 273 | resolution: "find-cache-dir@npm:3.3.2" 274 | dependencies: 275 | commondir: ^1.0.1 276 | make-dir: ^3.0.2 277 | pkg-dir: ^4.1.0 278 | checksum: 1e61c2e64f5c0b1c535bd85939ae73b0e5773142713273818cc0b393ee3555fb0fd44e1a5b161b8b6c3e03e98c2fcc9c227d784850a13a90a8ab576869576817 279 | languageName: node 280 | linkType: hard 281 | 282 | "find-replace@npm:^3.0.0": 283 | version: 3.0.0 284 | resolution: "find-replace@npm:3.0.0" 285 | dependencies: 286 | array-back: ^3.0.1 287 | checksum: 6b04bcfd79027f5b84aa1dfe100e3295da989bdac4b4de6b277f4d063e78f5c9e92ebc8a1fec6dd3b448c924ba404ee051cc759e14a3ee3e825fa1361025df08 288 | languageName: node 289 | linkType: hard 290 | 291 | "find-up@npm:^4.0.0": 292 | version: 4.1.0 293 | resolution: "find-up@npm:4.1.0" 294 | dependencies: 295 | locate-path: ^5.0.0 296 | path-exists: ^4.0.0 297 | checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 298 | languageName: node 299 | linkType: hard 300 | 301 | "flatbuffers@npm:^23.5.26": 302 | version: 23.5.26 303 | resolution: "flatbuffers@npm:23.5.26" 304 | checksum: 2528e549118d02fca9775cc9c17cf445741bb58b0a9575eb07bba823394a79dccb3bf97c48561720aa61d3dc9f42759129df0e05eb94c12f809cfb6126eaedd1 305 | languageName: node 306 | linkType: hard 307 | 308 | "fs-extra@npm:^11.1.1": 309 | version: 11.2.0 310 | resolution: "fs-extra@npm:11.2.0" 311 | dependencies: 312 | graceful-fs: ^4.2.0 313 | jsonfile: ^6.0.1 314 | universalify: ^2.0.0 315 | checksum: b12e42fa40ba47104202f57b8480dd098aa931c2724565e5e70779ab87605665594e76ee5fb00545f772ab9ace167fe06d2ab009c416dc8c842c5ae6df7aa7e8 316 | languageName: node 317 | linkType: hard 318 | 319 | "fs.realpath@npm:^1.0.0": 320 | version: 1.0.0 321 | resolution: "fs.realpath@npm:1.0.0" 322 | checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 323 | languageName: node 324 | linkType: hard 325 | 326 | "gh-pages@npm:^6.0.0": 327 | version: 6.1.0 328 | resolution: "gh-pages@npm:6.1.0" 329 | dependencies: 330 | async: ^3.2.4 331 | commander: ^11.0.0 332 | email-addresses: ^5.0.0 333 | filenamify: ^4.3.0 334 | find-cache-dir: ^3.3.1 335 | fs-extra: ^11.1.1 336 | globby: ^6.1.0 337 | bin: 338 | gh-pages: bin/gh-pages.js 339 | gh-pages-clean: bin/gh-pages-clean.js 340 | checksum: aa8a836869f49203b9fe6f7b2e5b02fbe38349036f5f0a8b0e3d0a6bfae81d02a3212971ac58e04948f9830215a0f94a651b266e1cf83ebb8f1b86a22835f72d 341 | languageName: node 342 | linkType: hard 343 | 344 | "glob@npm:^7.0.3": 345 | version: 7.2.3 346 | resolution: "glob@npm:7.2.3" 347 | dependencies: 348 | fs.realpath: ^1.0.0 349 | inflight: ^1.0.4 350 | inherits: 2 351 | minimatch: ^3.1.1 352 | once: ^1.3.0 353 | path-is-absolute: ^1.0.0 354 | checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 355 | languageName: node 356 | linkType: hard 357 | 358 | "globby@npm:^6.1.0": 359 | version: 6.1.0 360 | resolution: "globby@npm:6.1.0" 361 | dependencies: 362 | array-union: ^1.0.1 363 | glob: ^7.0.3 364 | object-assign: ^4.0.1 365 | pify: ^2.0.0 366 | pinkie-promise: ^2.0.0 367 | checksum: 18109d6b9d55643d2b98b59c3cfae7073ccfe39829632f353d516cc124d836c2ddebe48a23f04af63d66a621b6d86dd4cbd7e6af906f2458a7fe510ffc4bd424 368 | languageName: node 369 | linkType: hard 370 | 371 | "graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0": 372 | version: 4.2.11 373 | resolution: "graceful-fs@npm:4.2.11" 374 | checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 375 | languageName: node 376 | linkType: hard 377 | 378 | "has-flag@npm:^4.0.0": 379 | version: 4.0.0 380 | resolution: "has-flag@npm:4.0.0" 381 | checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad 382 | languageName: node 383 | linkType: hard 384 | 385 | "inflight@npm:^1.0.4": 386 | version: 1.0.6 387 | resolution: "inflight@npm:1.0.6" 388 | dependencies: 389 | once: ^1.3.0 390 | wrappy: 1 391 | checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd 392 | languageName: node 393 | linkType: hard 394 | 395 | "inherits@npm:2": 396 | version: 2.0.4 397 | resolution: "inherits@npm:2.0.4" 398 | checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 399 | languageName: node 400 | linkType: hard 401 | 402 | "json-bignum@npm:^0.0.3": 403 | version: 0.0.3 404 | resolution: "json-bignum@npm:0.0.3" 405 | checksum: e64b69089fa6760ef6373138754fece6467110a769a57991f6c9f0abf203413606540200e0682c8d3b377421aa9584eeccfaef424f7d8253b3b74c6b670b2fab 406 | languageName: node 407 | linkType: hard 408 | 409 | "jsonc-parser@npm:^3.2.0": 410 | version: 3.2.0 411 | resolution: "jsonc-parser@npm:3.2.0" 412 | checksum: 946dd9a5f326b745aa326d48a7257e3f4a4b62c5e98ec8e49fa2bdd8d96cef7e6febf1399f5c7016114fd1f68a1c62c6138826d5d90bc650448e3cf0951c53c7 413 | languageName: node 414 | linkType: hard 415 | 416 | "jsonfile@npm:^6.0.1": 417 | version: 6.1.0 418 | resolution: "jsonfile@npm:6.1.0" 419 | dependencies: 420 | graceful-fs: ^4.1.6 421 | universalify: ^2.0.0 422 | dependenciesMeta: 423 | graceful-fs: 424 | optional: true 425 | checksum: 7af3b8e1ac8fe7f1eccc6263c6ca14e1966fcbc74b618d3c78a0a2075579487547b94f72b7a1114e844a1e15bb00d440e5d1720bfc4612d790a6f285d5ea8354 426 | languageName: node 427 | linkType: hard 428 | 429 | "locate-path@npm:^5.0.0": 430 | version: 5.0.0 431 | resolution: "locate-path@npm:5.0.0" 432 | dependencies: 433 | p-locate: ^4.1.0 434 | checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 435 | languageName: node 436 | linkType: hard 437 | 438 | "lodash.assignwith@npm:^4.2.0": 439 | version: 4.2.0 440 | resolution: "lodash.assignwith@npm:4.2.0" 441 | checksum: 014a88e398802ca4eaae314afb67f32eb2cab6f01e61490dbbb74694263f79715341ab8ddf4b344093a2253b506d347f67731f0499e457d9c0128be1d2caf6dd 442 | languageName: node 443 | linkType: hard 444 | 445 | "lodash.camelcase@npm:^4.3.0": 446 | version: 4.3.0 447 | resolution: "lodash.camelcase@npm:4.3.0" 448 | checksum: cb9227612f71b83e42de93eccf1232feeb25e705bdb19ba26c04f91e885bfd3dd5c517c4a97137658190581d3493ea3973072ca010aab7e301046d90740393d1 449 | languageName: node 450 | linkType: hard 451 | 452 | "lunr@npm:^2.3.9": 453 | version: 2.3.9 454 | resolution: "lunr@npm:2.3.9" 455 | checksum: 176719e24fcce7d3cf1baccce9dd5633cd8bdc1f41ebe6a180112e5ee99d80373fe2454f5d4624d437e5a8319698ca6837b9950566e15d2cae5f2a543a3db4b8 456 | languageName: node 457 | linkType: hard 458 | 459 | "make-dir@npm:^3.0.2": 460 | version: 3.1.0 461 | resolution: "make-dir@npm:3.1.0" 462 | dependencies: 463 | semver: ^6.0.0 464 | checksum: 484200020ab5a1fdf12f393fe5f385fc8e4378824c940fba1729dcd198ae4ff24867bc7a5646331e50cead8abff5d9270c456314386e629acec6dff4b8016b78 465 | languageName: node 466 | linkType: hard 467 | 468 | "marked@npm:^4.3.0": 469 | version: 4.3.0 470 | resolution: "marked@npm:4.3.0" 471 | bin: 472 | marked: bin/marked.js 473 | checksum: 0db6817893952c3ec710eb9ceafb8468bf5ae38cb0f92b7b083baa13d70b19774674be04db5b817681fa7c5c6a088f61300815e4dd75a59696f4716ad69f6260 474 | languageName: node 475 | linkType: hard 476 | 477 | "minimatch@npm:^3.1.1": 478 | version: 3.1.2 479 | resolution: "minimatch@npm:3.1.2" 480 | dependencies: 481 | brace-expansion: ^1.1.7 482 | checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a 483 | languageName: node 484 | linkType: hard 485 | 486 | "minimatch@npm:^9.0.3": 487 | version: 9.0.3 488 | resolution: "minimatch@npm:9.0.3" 489 | dependencies: 490 | brace-expansion: ^2.0.1 491 | checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 492 | languageName: node 493 | linkType: hard 494 | 495 | "object-assign@npm:^4.0.1": 496 | version: 4.1.1 497 | resolution: "object-assign@npm:4.1.1" 498 | checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f 499 | languageName: node 500 | linkType: hard 501 | 502 | "once@npm:^1.3.0": 503 | version: 1.4.0 504 | resolution: "once@npm:1.4.0" 505 | dependencies: 506 | wrappy: 1 507 | checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 508 | languageName: node 509 | linkType: hard 510 | 511 | "p-limit@npm:^2.2.0": 512 | version: 2.3.0 513 | resolution: "p-limit@npm:2.3.0" 514 | dependencies: 515 | p-try: ^2.0.0 516 | checksum: 84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 517 | languageName: node 518 | linkType: hard 519 | 520 | "p-locate@npm:^4.1.0": 521 | version: 4.1.0 522 | resolution: "p-locate@npm:4.1.0" 523 | dependencies: 524 | p-limit: ^2.2.0 525 | checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 526 | languageName: node 527 | linkType: hard 528 | 529 | "p-try@npm:^2.0.0": 530 | version: 2.2.0 531 | resolution: "p-try@npm:2.2.0" 532 | checksum: f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae 533 | languageName: node 534 | linkType: hard 535 | 536 | "path-exists@npm:^4.0.0": 537 | version: 4.0.0 538 | resolution: "path-exists@npm:4.0.0" 539 | checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 540 | languageName: node 541 | linkType: hard 542 | 543 | "path-is-absolute@npm:^1.0.0": 544 | version: 1.0.1 545 | resolution: "path-is-absolute@npm:1.0.1" 546 | checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 547 | languageName: node 548 | linkType: hard 549 | 550 | "pify@npm:^2.0.0": 551 | version: 2.3.0 552 | resolution: "pify@npm:2.3.0" 553 | checksum: 9503aaeaf4577acc58642ad1d25c45c6d90288596238fb68f82811c08104c800e5a7870398e9f015d82b44ecbcbef3dc3d4251a1cbb582f6e5959fe09884b2ba 554 | languageName: node 555 | linkType: hard 556 | 557 | "pinkie-promise@npm:^2.0.0": 558 | version: 2.0.1 559 | resolution: "pinkie-promise@npm:2.0.1" 560 | dependencies: 561 | pinkie: ^2.0.0 562 | checksum: b53a4a2e73bf56b6f421eef711e7bdcb693d6abb474d57c5c413b809f654ba5ee750c6a96dd7225052d4b96c4d053cdcb34b708a86fceed4663303abee52fcca 563 | languageName: node 564 | linkType: hard 565 | 566 | "pinkie@npm:^2.0.0": 567 | version: 2.0.4 568 | resolution: "pinkie@npm:2.0.4" 569 | checksum: b12b10afea1177595aab036fc220785488f67b4b0fc49e7a27979472592e971614fa1c728e63ad3e7eb748b4ec3c3dbd780819331dad6f7d635c77c10537b9db 570 | languageName: node 571 | linkType: hard 572 | 573 | "pkg-dir@npm:^4.1.0": 574 | version: 4.2.0 575 | resolution: "pkg-dir@npm:4.2.0" 576 | dependencies: 577 | find-up: ^4.0.0 578 | checksum: 9863e3f35132bf99ae1636d31ff1e1e3501251d480336edb1c211133c8d58906bed80f154a1d723652df1fda91e01c7442c2eeaf9dc83157c7ae89087e43c8d6 579 | languageName: node 580 | linkType: hard 581 | 582 | "semver@npm:^6.0.0": 583 | version: 6.3.1 584 | resolution: "semver@npm:6.3.1" 585 | bin: 586 | semver: bin/semver.js 587 | checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 588 | languageName: node 589 | linkType: hard 590 | 591 | "shiki@npm:^0.14.1": 592 | version: 0.14.7 593 | resolution: "shiki@npm:0.14.7" 594 | dependencies: 595 | ansi-sequence-parser: ^1.1.0 596 | jsonc-parser: ^3.2.0 597 | vscode-oniguruma: ^1.7.0 598 | vscode-textmate: ^8.0.0 599 | checksum: 2aec3b3519df977c4391df9e1825cb496e9a4d7e11395f05a0da77e4fa2f7c3d9d6e6ee94029ac699533017f2b25637ee68f6d39f05f311535c2704d0329b520 600 | languageName: node 601 | linkType: hard 602 | 603 | "stream-read-all@npm:^3.0.1": 604 | version: 3.0.1 605 | resolution: "stream-read-all@npm:3.0.1" 606 | checksum: 40d3c286837f1b1ae7e8105959804ad42fda00f2c087722d981cb1c9fbbea892b8a0a7ca1cf6a016c96770151a6201a3da5c8b66fe35e35106b52a5e9ab90e3e 607 | languageName: node 608 | linkType: hard 609 | 610 | "strip-outer@npm:^1.0.1": 611 | version: 1.0.1 612 | resolution: "strip-outer@npm:1.0.1" 613 | dependencies: 614 | escape-string-regexp: ^1.0.2 615 | checksum: f8d65d33ca2b49aabc66bb41d689dda7b8b9959d320e3a40a2ef4d7079ff2f67ffb72db43f179f48dbf9495c2e33742863feab7a584d180fa62505439162c191 616 | languageName: node 617 | linkType: hard 618 | 619 | "supports-color@npm:^7.1.0": 620 | version: 7.2.0 621 | resolution: "supports-color@npm:7.2.0" 622 | dependencies: 623 | has-flag: ^4.0.0 624 | checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a 625 | languageName: node 626 | linkType: hard 627 | 628 | "table-layout@npm:^3.0.0": 629 | version: 3.0.2 630 | resolution: "table-layout@npm:3.0.2" 631 | dependencies: 632 | "@75lb/deep-merge": ^1.1.1 633 | array-back: ^6.2.2 634 | command-line-args: ^5.2.1 635 | command-line-usage: ^7.0.0 636 | stream-read-all: ^3.0.1 637 | typical: ^7.1.1 638 | wordwrapjs: ^5.1.0 639 | bin: 640 | table-layout: bin/cli.js 641 | checksum: 2d4c538f224e64321d35788dbf78305cc1d138a3508e1a29f33e4f6b00bd082990a45dc85fd92948213f48ed8c0b3599155c2a05de412661ff020635e0db3762 642 | languageName: node 643 | linkType: hard 644 | 645 | "trim-repeated@npm:^1.0.0": 646 | version: 1.0.0 647 | resolution: "trim-repeated@npm:1.0.0" 648 | dependencies: 649 | escape-string-regexp: ^1.0.2 650 | checksum: e25c235305b82c43f1d64a67a71226c406b00281755e4c2c4f3b1d0b09c687a535dd3c4483327f949f28bb89dc400a0bc5e5b749054f4b99f49ebfe48ba36496 651 | languageName: node 652 | linkType: hard 653 | 654 | "tslib@npm:^2.4.0, tslib@npm:^2.6.2": 655 | version: 2.6.2 656 | resolution: "tslib@npm:2.6.2" 657 | checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad 658 | languageName: node 659 | linkType: hard 660 | 661 | "typedoc@npm:^0.25.1": 662 | version: 0.25.4 663 | resolution: "typedoc@npm:0.25.4" 664 | dependencies: 665 | lunr: ^2.3.9 666 | marked: ^4.3.0 667 | minimatch: ^9.0.3 668 | shiki: ^0.14.1 669 | peerDependencies: 670 | typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x 671 | bin: 672 | typedoc: bin/typedoc 673 | checksum: 6d441baa277c0db4d577db2932a7af316d175415841e2faf2e68e3eda6ad60356c54f56374f89c5233d7bd5c057b0337455e5d484d8463e1445e67c37a6d94eb 674 | languageName: node 675 | linkType: hard 676 | 677 | "typescript@npm:^5.2.2": 678 | version: 5.3.3 679 | resolution: "typescript@npm:5.3.3" 680 | bin: 681 | tsc: bin/tsc 682 | tsserver: bin/tsserver 683 | checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 684 | languageName: node 685 | linkType: hard 686 | 687 | "typescript@patch:typescript@^5.2.2#~builtin": 688 | version: 5.3.3 689 | resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=f3b441" 690 | bin: 691 | tsc: bin/tsc 692 | tsserver: bin/tsserver 693 | checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 694 | languageName: node 695 | linkType: hard 696 | 697 | "typical@npm:^4.0.0": 698 | version: 4.0.0 699 | resolution: "typical@npm:4.0.0" 700 | checksum: a242081956825328f535e6195a924240b34daf6e7fdb573a1809a42b9f37fb8114fa99c7ab89a695e0cdb419d4149d067f6723e4b95855ffd39c6c4ca378efb3 701 | languageName: node 702 | linkType: hard 703 | 704 | "typical@npm:^7.1.1": 705 | version: 7.1.1 706 | resolution: "typical@npm:7.1.1" 707 | checksum: 292c64a2e3d2296fd1b7a92bbe3a9ad683f643f3faa8c9b45f6911105da54246817a3e2a4f0fdd01bb4c49d2b940618ad30b6771ac1c94bf690a40c706f657fa 708 | languageName: node 709 | linkType: hard 710 | 711 | "undici-types@npm:~5.26.4": 712 | version: 5.26.5 713 | resolution: "undici-types@npm:5.26.5" 714 | checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 715 | languageName: node 716 | linkType: hard 717 | 718 | "universalify@npm:^2.0.0": 719 | version: 2.0.1 720 | resolution: "universalify@npm:2.0.1" 721 | checksum: ecd8469fe0db28e7de9e5289d32bd1b6ba8f7183db34f3bfc4ca53c49891c2d6aa05f3fb3936a81285a905cc509fb641a0c3fc131ec786167eff41236ae32e60 722 | languageName: node 723 | linkType: hard 724 | 725 | "vscode-oniguruma@npm:^1.7.0": 726 | version: 1.7.0 727 | resolution: "vscode-oniguruma@npm:1.7.0" 728 | checksum: 53519d91d90593e6fb080260892e87d447e9b200c4964d766772b5053f5699066539d92100f77f1302c91e8fc5d9c772fbe40fe4c90f3d411a96d5a9b1e63f42 729 | languageName: node 730 | linkType: hard 731 | 732 | "vscode-textmate@npm:^8.0.0": 733 | version: 8.0.0 734 | resolution: "vscode-textmate@npm:8.0.0" 735 | checksum: 127780dfea89559d70b8326df6ec344cfd701312dd7f3f591a718693812b7852c30b6715e3cfc8b3200a4e2515b4c96f0843c0eacc0a3020969b5de262c2a4bb 736 | languageName: node 737 | linkType: hard 738 | 739 | "wordwrapjs@npm:^5.1.0": 740 | version: 5.1.0 741 | resolution: "wordwrapjs@npm:5.1.0" 742 | checksum: 063c7a5a85b694be1a5fd96f7ae0c0f4d717a087909e5c70cf25edec6eb5df5f2f5561f23e939cf6d7514cf81902610f74f288ef1612a49bf5451de15e0e29db 743 | languageName: node 744 | linkType: hard 745 | 746 | "wrappy@npm:1": 747 | version: 1.0.2 748 | resolution: "wrappy@npm:1.0.2" 749 | checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 750 | languageName: node 751 | linkType: hard 752 | --------------------------------------------------------------------------------