├── .Rbuildignore ├── .github └── workflows │ ├── docs.yml │ └── msrv.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── README.md ├── r ├── .Rbuildignore ├── DESCRIPTION ├── NAMESPACE ├── R │ └── extendr-wrappers.R ├── arrow-extendr.Rproj └── src │ ├── .gitignore │ ├── Makevars │ ├── Makevars.ucrt │ ├── Makevars.win │ ├── arrowextendr-win.def │ ├── entrypoint.c │ └── rust │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── lib.rs └── src ├── from.rs ├── lib.rs └── to.rs /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^arrow-extendr\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^src/\.cargo$ 4 | ^README\.Rmd$ 5 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | # 2 | name: Deploy static content to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: [main] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 19 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 20 | concurrency: 21 | group: "pages" 22 | cancel-in-progress: false 23 | 24 | jobs: 25 | # Single deploy job since we're just deploying 26 | deploy: 27 | environment: 28 | name: github-pages 29 | url: ${{ steps.deployment.outputs.page_url }} 30 | runs-on: ubuntu-latest 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v4 34 | 35 | - uses: dtolnay/rust-toolchain@nightly 36 | if: matrix.config.rust == 'nightly' 37 | 38 | - name: Docs 39 | run: cargo doc --no-deps --all-features 40 | env: 41 | RUSTDOCFLAGS: "--enable-index-page -Zunstable-options" 42 | 43 | - name: Setup Pages 44 | uses: actions/configure-pages@v3 45 | 46 | # As of v1.0.9, upload-pages-artifact action rejects files with incorrect permissions. 47 | # In Rust doc's case, .lock is such a file. 48 | # 49 | # cf. https://github.com/actions/deploy-pages/issues/188#issuecomment-1597651901 50 | - name: Remove unnecessary files 51 | run: rm -f ./target/doc/.lock 52 | 53 | - name: Upload artifact 54 | uses: actions/upload-pages-artifact@v2 55 | with: 56 | path: './target/doc' 57 | 58 | - name: Deploy to GitHub Pages 59 | id: deployment 60 | uses: actions/deploy-pages@v2 -------------------------------------------------------------------------------- /.github/workflows/msrv.yml: -------------------------------------------------------------------------------- 1 | name: Check MSRV 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths: 7 | - src/**/*.rs 8 | - Cargo.toml 9 | pull_request: 10 | branches: 11 | - main 12 | paths: 13 | - src/**/*.rs 14 | - Cargo.toml 15 | workflow_dispatch: 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | test-min-rust-version: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: baptiste0928/cargo-install@v2 27 | with: 28 | crate: cargo-msrv 29 | - name: Verify minimum rust version 30 | run: cargo-msrv verify -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode/ 2 | /target 3 | .Rproj.user 4 | */.DS_store 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 52.0.0 2 | 3 | - Release compatible with arrow-rs 52.0.0 4 | 5 | ## 51.0.0 6 | 7 | - Release compatible with arrow-rs 51.0.0 8 | 9 | ## 50.0.0 10 | 11 | - Release compatible with arrow-rs 50.0.0 12 | 13 | ## 49.0.0-geoarrow (2027-11-28) 14 | 15 | - Release compatible with geoarrow-rs based on [the Cargo.toml](https://github.com/geoarrow/geoarrow-rs/blob/9a0df7fad02fd5d4c84a23fe3ebf1a5d05e71d1e/Cargo.toml) 16 | 17 | ## 49.0.0 (2027-11-27) 18 | 19 | - Release compatible with arrow-rs 49.0.0 20 | 21 | ## 48.0.1 (2027-11-27) 22 | 23 | - Initial Crates.io release compatible with arrow-rs 48.0.1 24 | -------------------------------------------------------------------------------- /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 = "aho-corasick" 21 | version = "1.1.3" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 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 = "55.1.0" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "b1bb018b6960c87fd9d025009820406f74e83281185a8bdcb44880d2aa5c9a87" 48 | dependencies = [ 49 | "arrow-arith", 50 | "arrow-array", 51 | "arrow-buffer", 52 | "arrow-cast", 53 | "arrow-csv", 54 | "arrow-data", 55 | "arrow-ipc", 56 | "arrow-json", 57 | "arrow-ord", 58 | "arrow-row", 59 | "arrow-schema", 60 | "arrow-select", 61 | "arrow-string", 62 | ] 63 | 64 | [[package]] 65 | name = "arrow-arith" 66 | version = "55.1.0" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "44de76b51473aa888ecd6ad93ceb262fb8d40d1f1154a4df2f069b3590aa7575" 69 | dependencies = [ 70 | "arrow-array", 71 | "arrow-buffer", 72 | "arrow-data", 73 | "arrow-schema", 74 | "chrono", 75 | "num", 76 | ] 77 | 78 | [[package]] 79 | name = "arrow-array" 80 | version = "55.1.0" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "29ed77e22744475a9a53d00026cf8e166fe73cf42d89c4c4ae63607ee1cfcc3f" 83 | dependencies = [ 84 | "ahash", 85 | "arrow-buffer", 86 | "arrow-data", 87 | "arrow-schema", 88 | "chrono", 89 | "half", 90 | "hashbrown 0.15.2", 91 | "num", 92 | ] 93 | 94 | [[package]] 95 | name = "arrow-buffer" 96 | version = "55.1.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "b0391c96eb58bf7389171d1e103112d3fc3e5625ca6b372d606f2688f1ea4cce" 99 | dependencies = [ 100 | "bytes", 101 | "half", 102 | "num", 103 | ] 104 | 105 | [[package]] 106 | name = "arrow-cast" 107 | version = "55.1.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "f39e1d774ece9292697fcbe06b5584401b26bd34be1bec25c33edae65c2420ff" 110 | dependencies = [ 111 | "arrow-array", 112 | "arrow-buffer", 113 | "arrow-data", 114 | "arrow-schema", 115 | "arrow-select", 116 | "atoi", 117 | "base64", 118 | "chrono", 119 | "half", 120 | "lexical-core", 121 | "num", 122 | "ryu", 123 | ] 124 | 125 | [[package]] 126 | name = "arrow-csv" 127 | version = "55.1.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "9055c972a07bf12c2a827debfd34f88d3b93da1941d36e1d9fee85eebe38a12a" 130 | dependencies = [ 131 | "arrow-array", 132 | "arrow-cast", 133 | "arrow-schema", 134 | "chrono", 135 | "csv", 136 | "csv-core", 137 | "lazy_static", 138 | "regex", 139 | ] 140 | 141 | [[package]] 142 | name = "arrow-data" 143 | version = "55.1.0" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "cf75ac27a08c7f48b88e5c923f267e980f27070147ab74615ad85b5c5f90473d" 146 | dependencies = [ 147 | "arrow-buffer", 148 | "arrow-schema", 149 | "half", 150 | "num", 151 | ] 152 | 153 | [[package]] 154 | name = "arrow-ipc" 155 | version = "55.1.0" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "a222f0d93772bd058d1268f4c28ea421a603d66f7979479048c429292fac7b2e" 158 | dependencies = [ 159 | "arrow-array", 160 | "arrow-buffer", 161 | "arrow-data", 162 | "arrow-schema", 163 | "flatbuffers", 164 | ] 165 | 166 | [[package]] 167 | name = "arrow-json" 168 | version = "55.1.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "9085342bbca0f75e8cb70513c0807cc7351f1fbf5cb98192a67d5e3044acb033" 171 | dependencies = [ 172 | "arrow-array", 173 | "arrow-buffer", 174 | "arrow-cast", 175 | "arrow-data", 176 | "arrow-schema", 177 | "chrono", 178 | "half", 179 | "indexmap", 180 | "lexical-core", 181 | "memchr", 182 | "num", 183 | "serde", 184 | "serde_json", 185 | "simdutf8", 186 | ] 187 | 188 | [[package]] 189 | name = "arrow-ord" 190 | version = "55.1.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "ab2f1065a5cad7b9efa9e22ce5747ce826aa3855766755d4904535123ef431e7" 193 | dependencies = [ 194 | "arrow-array", 195 | "arrow-buffer", 196 | "arrow-data", 197 | "arrow-schema", 198 | "arrow-select", 199 | ] 200 | 201 | [[package]] 202 | name = "arrow-row" 203 | version = "55.1.0" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "3703a0e3e92d23c3f756df73d2dc9476873f873a76ae63ef9d3de17fda83b2d8" 206 | dependencies = [ 207 | "arrow-array", 208 | "arrow-buffer", 209 | "arrow-data", 210 | "arrow-schema", 211 | "half", 212 | ] 213 | 214 | [[package]] 215 | name = "arrow-schema" 216 | version = "55.1.0" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "73a47aa0c771b5381de2b7f16998d351a6f4eb839f1e13d48353e17e873d969b" 219 | dependencies = [ 220 | "bitflags", 221 | ] 222 | 223 | [[package]] 224 | name = "arrow-select" 225 | version = "55.1.0" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "24b7b85575702b23b85272b01bc1c25a01c9b9852305e5d0078c79ba25d995d4" 228 | dependencies = [ 229 | "ahash", 230 | "arrow-array", 231 | "arrow-buffer", 232 | "arrow-data", 233 | "arrow-schema", 234 | "num", 235 | ] 236 | 237 | [[package]] 238 | name = "arrow-string" 239 | version = "55.1.0" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "9260fddf1cdf2799ace2b4c2fc0356a9789fa7551e0953e35435536fecefebbd" 242 | dependencies = [ 243 | "arrow-array", 244 | "arrow-buffer", 245 | "arrow-data", 246 | "arrow-schema", 247 | "arrow-select", 248 | "memchr", 249 | "num", 250 | "regex", 251 | "regex-syntax", 252 | ] 253 | 254 | [[package]] 255 | name = "arrow_extendr" 256 | version = "55.1.0" 257 | dependencies = [ 258 | "arrow", 259 | "extendr-api", 260 | ] 261 | 262 | [[package]] 263 | name = "atoi" 264 | version = "2.0.0" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 267 | dependencies = [ 268 | "num-traits", 269 | ] 270 | 271 | [[package]] 272 | name = "autocfg" 273 | version = "1.3.0" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 276 | 277 | [[package]] 278 | name = "base64" 279 | version = "0.22.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 282 | 283 | [[package]] 284 | name = "bitflags" 285 | version = "2.9.1" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 288 | 289 | [[package]] 290 | name = "build-print" 291 | version = "0.1.1" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "4a2128d00b7061b82b72844a351e80acd29e05afc60e9261e2ac90dca9ecc2ac" 294 | 295 | [[package]] 296 | name = "bumpalo" 297 | version = "3.16.0" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 300 | 301 | [[package]] 302 | name = "bytes" 303 | version = "1.6.1" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" 306 | 307 | [[package]] 308 | name = "cc" 309 | version = "1.1.2" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "47de7e88bbbd467951ae7f5a6f34f70d1b4d9cfce53d5fd70f74ebe118b3db56" 312 | 313 | [[package]] 314 | name = "cfg-if" 315 | version = "1.0.0" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 318 | 319 | [[package]] 320 | name = "chrono" 321 | version = "0.4.41" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" 324 | dependencies = [ 325 | "android-tzdata", 326 | "iana-time-zone", 327 | "num-traits", 328 | "windows-link", 329 | ] 330 | 331 | [[package]] 332 | name = "const-random" 333 | version = "0.1.18" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" 336 | dependencies = [ 337 | "const-random-macro", 338 | ] 339 | 340 | [[package]] 341 | name = "const-random-macro" 342 | version = "0.1.16" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 345 | dependencies = [ 346 | "getrandom", 347 | "once_cell", 348 | "tiny-keccak", 349 | ] 350 | 351 | [[package]] 352 | name = "core-foundation-sys" 353 | version = "0.8.6" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" 356 | 357 | [[package]] 358 | name = "crunchy" 359 | version = "0.2.2" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 362 | 363 | [[package]] 364 | name = "csv" 365 | version = "1.3.0" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" 368 | dependencies = [ 369 | "csv-core", 370 | "itoa", 371 | "ryu", 372 | "serde", 373 | ] 374 | 375 | [[package]] 376 | name = "csv-core" 377 | version = "0.1.11" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" 380 | dependencies = [ 381 | "memchr", 382 | ] 383 | 384 | [[package]] 385 | name = "equivalent" 386 | version = "1.0.1" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 389 | 390 | [[package]] 391 | name = "extendr-api" 392 | version = "0.8.0" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "cae12193370e4f00f4a54b64f40dabc753ad755f15229c367e4b5851ed206954" 395 | dependencies = [ 396 | "extendr-ffi", 397 | "extendr-macros", 398 | "once_cell", 399 | "paste", 400 | ] 401 | 402 | [[package]] 403 | name = "extendr-ffi" 404 | version = "0.8.0" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "b48f96b7a4a2ff009ad9087f22a6de2312731a4096b520e3eb1c483df476ae95" 407 | dependencies = [ 408 | "build-print", 409 | ] 410 | 411 | [[package]] 412 | name = "extendr-macros" 413 | version = "0.8.0" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "fdbbac9afddafddb4dabd10aefa8082e3f057ec5bfa519c7b44af114e7ebf1a5" 416 | dependencies = [ 417 | "proc-macro2", 418 | "quote", 419 | "syn", 420 | ] 421 | 422 | [[package]] 423 | name = "flatbuffers" 424 | version = "25.2.10" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "1045398c1bfd89168b5fd3f1fc11f6e70b34f6f66300c87d44d3de849463abf1" 427 | dependencies = [ 428 | "bitflags", 429 | "rustc_version", 430 | ] 431 | 432 | [[package]] 433 | name = "getrandom" 434 | version = "0.2.15" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 437 | dependencies = [ 438 | "cfg-if", 439 | "libc", 440 | "wasi", 441 | ] 442 | 443 | [[package]] 444 | name = "half" 445 | version = "2.4.1" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" 448 | dependencies = [ 449 | "cfg-if", 450 | "crunchy", 451 | "num-traits", 452 | ] 453 | 454 | [[package]] 455 | name = "hashbrown" 456 | version = "0.14.5" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 459 | 460 | [[package]] 461 | name = "hashbrown" 462 | version = "0.15.2" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 465 | 466 | [[package]] 467 | name = "iana-time-zone" 468 | version = "0.1.60" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" 471 | dependencies = [ 472 | "android_system_properties", 473 | "core-foundation-sys", 474 | "iana-time-zone-haiku", 475 | "js-sys", 476 | "wasm-bindgen", 477 | "windows-core", 478 | ] 479 | 480 | [[package]] 481 | name = "iana-time-zone-haiku" 482 | version = "0.1.2" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 485 | dependencies = [ 486 | "cc", 487 | ] 488 | 489 | [[package]] 490 | name = "indexmap" 491 | version = "2.2.6" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 494 | dependencies = [ 495 | "equivalent", 496 | "hashbrown 0.14.5", 497 | ] 498 | 499 | [[package]] 500 | name = "itoa" 501 | version = "1.0.11" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 504 | 505 | [[package]] 506 | name = "js-sys" 507 | version = "0.3.69" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" 510 | dependencies = [ 511 | "wasm-bindgen", 512 | ] 513 | 514 | [[package]] 515 | name = "lazy_static" 516 | version = "1.5.0" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 519 | 520 | [[package]] 521 | name = "lexical-core" 522 | version = "1.0.5" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "b765c31809609075565a70b4b71402281283aeda7ecaf4818ac14a7b2ade8958" 525 | dependencies = [ 526 | "lexical-parse-float", 527 | "lexical-parse-integer", 528 | "lexical-util", 529 | "lexical-write-float", 530 | "lexical-write-integer", 531 | ] 532 | 533 | [[package]] 534 | name = "lexical-parse-float" 535 | version = "1.0.5" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "de6f9cb01fb0b08060209a057c048fcbab8717b4c1ecd2eac66ebfe39a65b0f2" 538 | dependencies = [ 539 | "lexical-parse-integer", 540 | "lexical-util", 541 | "static_assertions", 542 | ] 543 | 544 | [[package]] 545 | name = "lexical-parse-integer" 546 | version = "1.0.5" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "72207aae22fc0a121ba7b6d479e42cbfea549af1479c3f3a4f12c70dd66df12e" 549 | dependencies = [ 550 | "lexical-util", 551 | "static_assertions", 552 | ] 553 | 554 | [[package]] 555 | name = "lexical-util" 556 | version = "1.0.6" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "5a82e24bf537fd24c177ffbbdc6ebcc8d54732c35b50a3f28cc3f4e4c949a0b3" 559 | dependencies = [ 560 | "static_assertions", 561 | ] 562 | 563 | [[package]] 564 | name = "lexical-write-float" 565 | version = "1.0.5" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "c5afc668a27f460fb45a81a757b6bf2f43c2d7e30cb5a2dcd3abf294c78d62bd" 568 | dependencies = [ 569 | "lexical-util", 570 | "lexical-write-integer", 571 | "static_assertions", 572 | ] 573 | 574 | [[package]] 575 | name = "lexical-write-integer" 576 | version = "1.0.5" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "629ddff1a914a836fb245616a7888b62903aae58fa771e1d83943035efa0f978" 579 | dependencies = [ 580 | "lexical-util", 581 | "static_assertions", 582 | ] 583 | 584 | [[package]] 585 | name = "libc" 586 | version = "0.2.155" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 589 | 590 | [[package]] 591 | name = "libm" 592 | version = "0.2.8" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 595 | 596 | [[package]] 597 | name = "log" 598 | version = "0.4.22" 599 | source = "registry+https://github.com/rust-lang/crates.io-index" 600 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 601 | 602 | [[package]] 603 | name = "memchr" 604 | version = "2.7.4" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 607 | 608 | [[package]] 609 | name = "num" 610 | version = "0.4.3" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" 613 | dependencies = [ 614 | "num-bigint", 615 | "num-complex", 616 | "num-integer", 617 | "num-iter", 618 | "num-rational", 619 | "num-traits", 620 | ] 621 | 622 | [[package]] 623 | name = "num-bigint" 624 | version = "0.4.6" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 627 | dependencies = [ 628 | "num-integer", 629 | "num-traits", 630 | ] 631 | 632 | [[package]] 633 | name = "num-complex" 634 | version = "0.4.6" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 637 | dependencies = [ 638 | "num-traits", 639 | ] 640 | 641 | [[package]] 642 | name = "num-integer" 643 | version = "0.1.46" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 646 | dependencies = [ 647 | "num-traits", 648 | ] 649 | 650 | [[package]] 651 | name = "num-iter" 652 | version = "0.1.45" 653 | source = "registry+https://github.com/rust-lang/crates.io-index" 654 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 655 | dependencies = [ 656 | "autocfg", 657 | "num-integer", 658 | "num-traits", 659 | ] 660 | 661 | [[package]] 662 | name = "num-rational" 663 | version = "0.4.2" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 666 | dependencies = [ 667 | "num-bigint", 668 | "num-integer", 669 | "num-traits", 670 | ] 671 | 672 | [[package]] 673 | name = "num-traits" 674 | version = "0.2.19" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 677 | dependencies = [ 678 | "autocfg", 679 | "libm", 680 | ] 681 | 682 | [[package]] 683 | name = "once_cell" 684 | version = "1.21.3" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 687 | 688 | [[package]] 689 | name = "paste" 690 | version = "1.0.15" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 693 | 694 | [[package]] 695 | name = "proc-macro2" 696 | version = "1.0.86" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 699 | dependencies = [ 700 | "unicode-ident", 701 | ] 702 | 703 | [[package]] 704 | name = "quote" 705 | version = "1.0.36" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 708 | dependencies = [ 709 | "proc-macro2", 710 | ] 711 | 712 | [[package]] 713 | name = "regex" 714 | version = "1.10.5" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" 717 | dependencies = [ 718 | "aho-corasick", 719 | "memchr", 720 | "regex-automata", 721 | "regex-syntax", 722 | ] 723 | 724 | [[package]] 725 | name = "regex-automata" 726 | version = "0.4.7" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 729 | dependencies = [ 730 | "aho-corasick", 731 | "memchr", 732 | "regex-syntax", 733 | ] 734 | 735 | [[package]] 736 | name = "regex-syntax" 737 | version = "0.8.4" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 740 | 741 | [[package]] 742 | name = "rustc_version" 743 | version = "0.4.0" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 746 | dependencies = [ 747 | "semver", 748 | ] 749 | 750 | [[package]] 751 | name = "ryu" 752 | version = "1.0.18" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 755 | 756 | [[package]] 757 | name = "semver" 758 | version = "1.0.23" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" 761 | 762 | [[package]] 763 | name = "serde" 764 | version = "1.0.204" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" 767 | dependencies = [ 768 | "serde_derive", 769 | ] 770 | 771 | [[package]] 772 | name = "serde_derive" 773 | version = "1.0.204" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" 776 | dependencies = [ 777 | "proc-macro2", 778 | "quote", 779 | "syn", 780 | ] 781 | 782 | [[package]] 783 | name = "serde_json" 784 | version = "1.0.120" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" 787 | dependencies = [ 788 | "itoa", 789 | "ryu", 790 | "serde", 791 | ] 792 | 793 | [[package]] 794 | name = "simdutf8" 795 | version = "0.1.5" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" 798 | 799 | [[package]] 800 | name = "static_assertions" 801 | version = "1.1.0" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 804 | 805 | [[package]] 806 | name = "syn" 807 | version = "2.0.71" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" 810 | dependencies = [ 811 | "proc-macro2", 812 | "quote", 813 | "unicode-ident", 814 | ] 815 | 816 | [[package]] 817 | name = "tiny-keccak" 818 | version = "2.0.2" 819 | source = "registry+https://github.com/rust-lang/crates.io-index" 820 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 821 | dependencies = [ 822 | "crunchy", 823 | ] 824 | 825 | [[package]] 826 | name = "unicode-ident" 827 | version = "1.0.12" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 830 | 831 | [[package]] 832 | name = "version_check" 833 | version = "0.9.4" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 836 | 837 | [[package]] 838 | name = "wasi" 839 | version = "0.11.0+wasi-snapshot-preview1" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 842 | 843 | [[package]] 844 | name = "wasm-bindgen" 845 | version = "0.2.92" 846 | source = "registry+https://github.com/rust-lang/crates.io-index" 847 | checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" 848 | dependencies = [ 849 | "cfg-if", 850 | "wasm-bindgen-macro", 851 | ] 852 | 853 | [[package]] 854 | name = "wasm-bindgen-backend" 855 | version = "0.2.92" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" 858 | dependencies = [ 859 | "bumpalo", 860 | "log", 861 | "once_cell", 862 | "proc-macro2", 863 | "quote", 864 | "syn", 865 | "wasm-bindgen-shared", 866 | ] 867 | 868 | [[package]] 869 | name = "wasm-bindgen-macro" 870 | version = "0.2.92" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" 873 | dependencies = [ 874 | "quote", 875 | "wasm-bindgen-macro-support", 876 | ] 877 | 878 | [[package]] 879 | name = "wasm-bindgen-macro-support" 880 | version = "0.2.92" 881 | source = "registry+https://github.com/rust-lang/crates.io-index" 882 | checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" 883 | dependencies = [ 884 | "proc-macro2", 885 | "quote", 886 | "syn", 887 | "wasm-bindgen-backend", 888 | "wasm-bindgen-shared", 889 | ] 890 | 891 | [[package]] 892 | name = "wasm-bindgen-shared" 893 | version = "0.2.92" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" 896 | 897 | [[package]] 898 | name = "windows-core" 899 | version = "0.52.0" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 902 | dependencies = [ 903 | "windows-targets", 904 | ] 905 | 906 | [[package]] 907 | name = "windows-link" 908 | version = "0.1.1" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 911 | 912 | [[package]] 913 | name = "windows-targets" 914 | version = "0.52.6" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 917 | dependencies = [ 918 | "windows_aarch64_gnullvm", 919 | "windows_aarch64_msvc", 920 | "windows_i686_gnu", 921 | "windows_i686_gnullvm", 922 | "windows_i686_msvc", 923 | "windows_x86_64_gnu", 924 | "windows_x86_64_gnullvm", 925 | "windows_x86_64_msvc", 926 | ] 927 | 928 | [[package]] 929 | name = "windows_aarch64_gnullvm" 930 | version = "0.52.6" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 933 | 934 | [[package]] 935 | name = "windows_aarch64_msvc" 936 | version = "0.52.6" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 939 | 940 | [[package]] 941 | name = "windows_i686_gnu" 942 | version = "0.52.6" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 945 | 946 | [[package]] 947 | name = "windows_i686_gnullvm" 948 | version = "0.52.6" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 951 | 952 | [[package]] 953 | name = "windows_i686_msvc" 954 | version = "0.52.6" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 957 | 958 | [[package]] 959 | name = "windows_x86_64_gnu" 960 | version = "0.52.6" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 963 | 964 | [[package]] 965 | name = "windows_x86_64_gnullvm" 966 | version = "0.52.6" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 969 | 970 | [[package]] 971 | name = "windows_x86_64_msvc" 972 | version = "0.52.6" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 975 | 976 | [[package]] 977 | name = "zerocopy" 978 | version = "0.7.35" 979 | source = "registry+https://github.com/rust-lang/crates.io-index" 980 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 981 | dependencies = [ 982 | "zerocopy-derive", 983 | ] 984 | 985 | [[package]] 986 | name = "zerocopy-derive" 987 | version = "0.7.35" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 990 | dependencies = [ 991 | "proc-macro2", 992 | "quote", 993 | "syn", 994 | ] 995 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = 'arrow_extendr' 3 | version = '55.1.0' 4 | edition = '2021' 5 | license = "MIT OR Apache-2.0" 6 | repository = "https://github.com/josiahparry/arrow-extendr" 7 | authors = ["Josiah Parry"] 8 | description = "Enables the use of arrow-rs in R using extendr and nanoarrow" 9 | categories = ["development-tools::ffi"] 10 | keywords = ["arrow", "extendr", "rstats"] 11 | readme = "README.md" 12 | 13 | include = ["src/*", "Cargo.toml", "README.md"] 14 | 15 | # matches arrow 16 | rust-version = "1.70.0" 17 | 18 | [lib] 19 | crate-type = ["staticlib", "lib"] 20 | name = 'arrow_extendr' 21 | 22 | [dependencies] 23 | arrow = { version = "55.1.0", features = ["ffi"] } 24 | extendr-api = '>=0.8.0' 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # arrow_extendr 2 | 3 | arrow-extendr is a crate that facilitates the transfer of [Apache Arrow](https://arrow.apache.org/) memory between R and Rust. It utilizes [extendr](https://extendr.github.io/), the [**`{nanoarrow}`**](https://arrow.apache.org/nanoarrow/0.3.0/r/index.html) R package, and [arrow-rs](https://docs.rs/arrow). 4 | 5 | ## Versioning 6 | 7 | At present, versions of arrow-rs are not compatible with each other. This means if your crate uses arrow-rs version `48.0.1`, then the arrow-extendr must also use that same version. As such, arrow-extendr uses the same versions as arrow-rs so that it is easy to match the required versions you need. 8 | 9 | **Versions**: 10 | 11 | - 55.1.0 12 | - 54.0.0 13 | - 53.0.0 14 | - 52.0.0 15 | - 51.0.0 16 | - 50.0.0 (compatible with geoarrow-rs 0.1.0) 17 | - 49.0.0-geoarrow (not available on crates.io but is the current Git version) 18 | - 48.0.1 19 | - 49.0.0 20 | 21 | ### Motivating Example 22 | 23 | Say we have the following `DBI` connection which we will send requests to using arrow. 24 | The result of `dbGetQueryArrow()` is a `nanoarrow_array_stream`. We want to 25 | count the number of rows in each batch of the steam using Rust. 26 | 27 | ```r 28 | # adapted from https://github.com/r-dbi/DBI/blob/main/vignettes/DBI-arrow.Rmd 29 | 30 | library(DBI) 31 | con <- dbConnect(RSQLite::SQLite()) 32 | data <- data.frame( 33 | a = runif(10000, 0, 10), 34 | b = rnorm(10000, 4.5), 35 | c = sample(letters, 10000, TRUE) 36 | ) 37 | 38 | dbWriteTable(con, "tbl", data) 39 | ``` 40 | 41 | We can write an extendr function which creates an `ArrowArrayStreamReader` 42 | from an `&Robj`. In the function we instantiate a counter to keep track 43 | of the number of rows per chunk. For each chunk we print the number of rows. 44 | 45 | ```rust 46 | use extendr_api::prelude::*; 47 | use arrow_extendr::from::FromArrowRobj; 48 | use arrow::ffi_stream::ArrowArrayStreamReader; 49 | 50 | #[extendr] 51 | /// @export 52 | fn process_stream(stream: Robj) -> i32 { 53 | let rb = ArrowArrayStreamReader::from_arrow_robj(&stream) 54 | .unwrap(); 55 | 56 | let mut n = 0; 57 | 58 | rprintln!("Processing `ArrowArrayStreamReader`..."); 59 | for chunk in rb { 60 | let chunk_rows = chunk.unwrap().num_rows(); 61 | rprintln!("Found {chunk_rows} rows"); 62 | n += chunk_rows as i32; 63 | } 64 | 65 | n 66 | } 67 | ``` 68 | 69 | With this function we can use it on the output of `dbGetQueryArrow()` or other Arrow 70 | related DBI functions. 71 | 72 | ```r 73 | query <- dbGetQueryArrow(con, "SELECT * FROM tbl WHERE a < 3") 74 | process_stream(query) 75 | #> Processing `ArrowArrayStreamReader`... 76 | #> Found 256 rows 77 | #> Found 256 rows 78 | #> Found 256 rows 79 | #> ... truncated ... 80 | #> Found 256 rows 81 | #> Found 256 rows 82 | #> Found 143 rows 83 | #> [1] 2959 84 | ``` 85 | 86 | ## Using arrow-extendr in a package 87 | 88 | To use arrow-extendr in an R package first create an R package and make it an extendr package with: 89 | 90 | ```r 91 | usethis::create_package("my_package") 92 | rextendr::use_extendr(); 93 | ``` 94 | 95 | Next, you have to ensure that `nanoarrow` is a dependency of the package since arrow-extendr will call functions from nanoarrow to convert between R and Arrow memory. To do this run `usethis::use_package("nanoarrow")` to add it to your Imports field in the DESCRIPTION file. 96 | -------------------------------------------------------------------------------- /r/.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^src/\.cargo$ 4 | -------------------------------------------------------------------------------- /r/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: arrowextendr 2 | Title: What the Package Does (One Line, Title Case) 3 | Version: 0.0.0.9000 4 | Authors@R: 5 | person("Josiah", "Parry", , "josiah.parry@gmail.com", role = c("aut", "cre"), 6 | comment = c(ORCID = "0000-0001-9910-865X")) 7 | Description: What the package does (one paragraph). 8 | License: MIT + file LICENSE 9 | Encoding: UTF-8 10 | Language: en 11 | Roxygen: list(markdown = TRUE) 12 | RoxygenNote: 7.2.3 13 | Config/rextendr/version: 0.3.1.9000 14 | SystemRequirements: Cargo (rustc package manager) 15 | Imports: 16 | arrow, 17 | nanoarrow 18 | -------------------------------------------------------------------------------- /r/NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(process_stream) 4 | export(test_datatype) 5 | export(test_f64) 6 | export(test_field) 7 | export(test_from_array) 8 | export(test_from_array_steam_reader) 9 | export(test_from_datatype) 10 | export(test_from_field) 11 | export(test_from_recordbatch) 12 | export(test_from_schema) 13 | export(test_i32) 14 | export(test_record_batch) 15 | export(test_schema) 16 | useDynLib(arrowextendr, .registration = TRUE) 17 | -------------------------------------------------------------------------------- /r/R/extendr-wrappers.R: -------------------------------------------------------------------------------- 1 | # Generated by extendr: Do not edit by hand 2 | 3 | # nolint start 4 | 5 | # 6 | # This file was created with the following call: 7 | # .Call("wrap__make_arrowextendr_wrappers", use_symbols = TRUE, package_name = "arrowextendr") 8 | 9 | #' @docType package 10 | #' @usage NULL 11 | #' @useDynLib arrowextendr, .registration = TRUE 12 | NULL 13 | 14 | #' @export 15 | test_i32 <- function() .Call(wrap__test_i32) 16 | 17 | #' @export 18 | test_f64 <- function() .Call(wrap__test_f64) 19 | 20 | #' @export 21 | test_field <- function() .Call(wrap__test_field) 22 | 23 | #' @export 24 | test_record_batch <- function() .Call(wrap__test_record_batch) 25 | 26 | #' @export 27 | test_schema <- function() .Call(wrap__test_schema) 28 | 29 | #' @export 30 | test_datatype <- function() .Call(wrap__test_datatype) 31 | 32 | #' @export 33 | test_from_field <- function(field) invisible(.Call(wrap__test_from_field, field)) 34 | 35 | #' @export 36 | test_from_datatype <- function(field) invisible(.Call(wrap__test_from_datatype, field)) 37 | 38 | #' @export 39 | test_from_schema <- function(field) invisible(.Call(wrap__test_from_schema, field)) 40 | 41 | #' @export 42 | test_from_array <- function(field) invisible(.Call(wrap__test_from_array, field)) 43 | 44 | #' @export 45 | test_from_recordbatch <- function(rb) invisible(.Call(wrap__test_from_recordbatch, rb)) 46 | 47 | #' @export 48 | test_from_array_steam_reader <- function(rb) invisible(.Call(wrap__test_from_array_steam_reader, rb)) 49 | 50 | #' @export 51 | process_stream <- function(stream) .Call(wrap__process_stream, stream) 52 | 53 | 54 | # nolint end 55 | -------------------------------------------------------------------------------- /r/arrow-extendr.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | LineEndingConversion: Posix 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /r/src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.dll 4 | target 5 | .cargo 6 | -------------------------------------------------------------------------------- /r/src/Makevars: -------------------------------------------------------------------------------- 1 | TARGET_DIR = ./rust/target 2 | LIBDIR = $(TARGET_DIR)/release 3 | STATLIB = $(LIBDIR)/libarrowextendr.a 4 | PKG_LIBS = -L$(LIBDIR) -larrowextendr 5 | 6 | all: C_clean 7 | 8 | $(SHLIB): $(STATLIB) 9 | 10 | CARGOTMP = $(CURDIR)/.cargo 11 | 12 | $(STATLIB): 13 | # In some environments, ~/.cargo/bin might not be included in PATH, so we need 14 | # to set it here to ensure cargo can be invoked. It is appended to PATH and 15 | # therefore is only used if cargo is absent from the user's PATH. 16 | if [ "$(NOT_CRAN)" != "true" ]; then \ 17 | export CARGO_HOME=$(CARGOTMP); \ 18 | fi && \ 19 | export PATH="$(PATH):$(HOME)/.cargo/bin" && \ 20 | cargo build --lib --release --manifest-path=./rust/Cargo.toml --target-dir $(TARGET_DIR) 21 | if [ "$(NOT_CRAN)" != "true" ]; then \ 22 | rm -Rf $(CARGOTMP) && \ 23 | rm -Rf $(LIBDIR)/build; \ 24 | fi 25 | 26 | C_clean: 27 | rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS) 28 | 29 | clean: 30 | rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS) rust/target 31 | -------------------------------------------------------------------------------- /r/src/Makevars.ucrt: -------------------------------------------------------------------------------- 1 | # Rtools42 doesn't have the linker in the location that cargo expects, so we 2 | # need to overwrite it via configuration. 3 | CARGO_LINKER = x86_64-w64-mingw32.static.posix-gcc.exe 4 | 5 | include Makevars.win 6 | -------------------------------------------------------------------------------- /r/src/Makevars.win: -------------------------------------------------------------------------------- 1 | TARGET = $(subst 64,x86_64,$(subst 32,i686,$(WIN)))-pc-windows-gnu 2 | 3 | TARGET_DIR = ./rust/target 4 | LIBDIR = $(TARGET_DIR)/$(TARGET)/release 5 | STATLIB = $(LIBDIR)/libarrowextendr.a 6 | PKG_LIBS = -L$(LIBDIR) -larrowextendr -lws2_32 -ladvapi32 -luserenv -lbcrypt -lntdll 7 | 8 | all: C_clean 9 | 10 | $(SHLIB): $(STATLIB) 11 | 12 | CARGOTMP = $(CURDIR)/.cargo 13 | 14 | $(STATLIB): 15 | mkdir -p $(TARGET_DIR)/libgcc_mock 16 | # `rustc` adds `-lgcc_eh` flags to the compiler, but Rtools' GCC doesn't have 17 | # `libgcc_eh` due to the compilation settings. So, in order to please the 18 | # compiler, we need to add empty `libgcc_eh` to the library search paths. 19 | # 20 | # For more details, please refer to 21 | # https://github.com/r-windows/rtools-packages/blob/2407b23f1e0925bbb20a4162c963600105236318/mingw-w64-gcc/PKGBUILD#L313-L316 22 | touch $(TARGET_DIR)/libgcc_mock/libgcc_eh.a 23 | 24 | # CARGO_LINKER is provided in Makevars.ucrt for R >= 4.2 25 | if [ "$(NOT_CRAN)" != "true" ]; then \ 26 | export CARGO_HOME=$(CARGOTMP); \ 27 | fi && \ 28 | export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER="$(CARGO_LINKER)" && \ 29 | export LIBRARY_PATH="$${LIBRARY_PATH};$(CURDIR)/$(TARGET_DIR)/libgcc_mock" && \ 30 | cargo build --target=$(TARGET) --lib --release --manifest-path=./rust/Cargo.toml --target-dir $(TARGET_DIR) 31 | if [ "$(NOT_CRAN)" != "true" ]; then \ 32 | rm -Rf $(CARGOTMP) && \ 33 | rm -Rf $(LIBDIR)/build; \ 34 | fi 35 | 36 | C_clean: 37 | rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS) 38 | 39 | clean: 40 | rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS) $(TARGET_DIR) 41 | -------------------------------------------------------------------------------- /r/src/arrowextendr-win.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | R_init_arrowextendr 3 | -------------------------------------------------------------------------------- /r/src/entrypoint.c: -------------------------------------------------------------------------------- 1 | // We need to forward routine registration from C to Rust 2 | // to avoid the linker removing the static library. 3 | 4 | void R_init_arrowextendr_extendr(void *dll); 5 | 6 | void R_init_arrowextendr(void *dll) { 7 | R_init_arrowextendr_extendr(dll); 8 | } 9 | -------------------------------------------------------------------------------- /r/src/rust/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-csv", 55 | "arrow-data", 56 | "arrow-ipc", 57 | "arrow-json", 58 | "arrow-ord", 59 | "arrow-row", 60 | "arrow-schema", 61 | "arrow-select", 62 | "arrow-string", 63 | ] 64 | 65 | [[package]] 66 | name = "arrow-arith" 67 | version = "49.0.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "34ccd45e217ffa6e53bbb0080990e77113bdd4e91ddb84e97b77649810bcf1a7" 70 | dependencies = [ 71 | "arrow-array", 72 | "arrow-buffer", 73 | "arrow-data", 74 | "arrow-schema", 75 | "chrono", 76 | "half", 77 | "num", 78 | ] 79 | 80 | [[package]] 81 | name = "arrow-array" 82 | version = "49.0.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "6bda9acea48b25123c08340f3a8ac361aa0f74469bb36f5ee9acf923fce23e9d" 85 | dependencies = [ 86 | "ahash", 87 | "arrow-buffer", 88 | "arrow-data", 89 | "arrow-schema", 90 | "chrono", 91 | "half", 92 | "hashbrown", 93 | "num", 94 | ] 95 | 96 | [[package]] 97 | name = "arrow-buffer" 98 | version = "49.0.0" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "01a0fc21915b00fc6c2667b069c1b64bdd920982f426079bc4a7cab86822886c" 101 | dependencies = [ 102 | "bytes", 103 | "half", 104 | "num", 105 | ] 106 | 107 | [[package]] 108 | name = "arrow-cast" 109 | version = "49.0.0" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "5dc0368ed618d509636c1e3cc20db1281148190a78f43519487b2daf07b63b4a" 112 | dependencies = [ 113 | "arrow-array", 114 | "arrow-buffer", 115 | "arrow-data", 116 | "arrow-schema", 117 | "arrow-select", 118 | "base64", 119 | "chrono", 120 | "half", 121 | "lexical-core", 122 | "num", 123 | ] 124 | 125 | [[package]] 126 | name = "arrow-csv" 127 | version = "49.0.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "2e09aa6246a1d6459b3f14baeaa49606cfdbca34435c46320e14054d244987ca" 130 | dependencies = [ 131 | "arrow-array", 132 | "arrow-buffer", 133 | "arrow-cast", 134 | "arrow-data", 135 | "arrow-schema", 136 | "chrono", 137 | "csv", 138 | "csv-core", 139 | "lazy_static", 140 | "lexical-core", 141 | "regex", 142 | ] 143 | 144 | [[package]] 145 | name = "arrow-data" 146 | version = "49.0.0" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "907fafe280a3874474678c1858b9ca4cb7fd83fb8034ff5b6d6376205a08c634" 149 | dependencies = [ 150 | "arrow-buffer", 151 | "arrow-schema", 152 | "half", 153 | "num", 154 | ] 155 | 156 | [[package]] 157 | name = "arrow-ipc" 158 | version = "49.0.0" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "79a43d6808411886b8c7d4f6f7dd477029c1e77ffffffb7923555cc6579639cd" 161 | dependencies = [ 162 | "arrow-array", 163 | "arrow-buffer", 164 | "arrow-cast", 165 | "arrow-data", 166 | "arrow-schema", 167 | "flatbuffers", 168 | ] 169 | 170 | [[package]] 171 | name = "arrow-json" 172 | version = "49.0.0" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "d82565c91fd627922ebfe2810ee4e8346841b6f9361b87505a9acea38b614fee" 175 | dependencies = [ 176 | "arrow-array", 177 | "arrow-buffer", 178 | "arrow-cast", 179 | "arrow-data", 180 | "arrow-schema", 181 | "chrono", 182 | "half", 183 | "indexmap", 184 | "lexical-core", 185 | "num", 186 | "serde", 187 | "serde_json", 188 | ] 189 | 190 | [[package]] 191 | name = "arrow-ord" 192 | version = "49.0.0" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "9b23b0e53c0db57c6749997fd343d4c0354c994be7eca67152dd2bdb9a3e1bb4" 195 | dependencies = [ 196 | "arrow-array", 197 | "arrow-buffer", 198 | "arrow-data", 199 | "arrow-schema", 200 | "arrow-select", 201 | "half", 202 | "num", 203 | ] 204 | 205 | [[package]] 206 | name = "arrow-row" 207 | version = "49.0.0" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "361249898d2d6d4a6eeb7484be6ac74977e48da12a4dd81a708d620cc558117a" 210 | dependencies = [ 211 | "ahash", 212 | "arrow-array", 213 | "arrow-buffer", 214 | "arrow-data", 215 | "arrow-schema", 216 | "half", 217 | "hashbrown", 218 | ] 219 | 220 | [[package]] 221 | name = "arrow-schema" 222 | version = "49.0.0" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "09e28a5e781bf1b0f981333684ad13f5901f4cd2f20589eab7cf1797da8fc167" 225 | dependencies = [ 226 | "bitflags 2.4.1", 227 | ] 228 | 229 | [[package]] 230 | name = "arrow-select" 231 | version = "49.0.0" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "4f6208466590960efc1d2a7172bc4ff18a67d6e25c529381d7f96ddaf0dc4036" 234 | dependencies = [ 235 | "ahash", 236 | "arrow-array", 237 | "arrow-buffer", 238 | "arrow-data", 239 | "arrow-schema", 240 | "num", 241 | ] 242 | 243 | [[package]] 244 | name = "arrow-string" 245 | version = "49.0.0" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "a4a48149c63c11c9ff571e50ab8f017d2a7cb71037a882b42f6354ed2da9acc7" 248 | dependencies = [ 249 | "arrow-array", 250 | "arrow-buffer", 251 | "arrow-data", 252 | "arrow-schema", 253 | "arrow-select", 254 | "num", 255 | "regex", 256 | "regex-syntax", 257 | ] 258 | 259 | [[package]] 260 | name = "arrow_extendr" 261 | version = "0.1.0" 262 | dependencies = [ 263 | "arrow", 264 | "extendr-api", 265 | ] 266 | 267 | [[package]] 268 | name = "arrowextendr" 269 | version = "0.1.0" 270 | dependencies = [ 271 | "arrow", 272 | "arrow_extendr", 273 | "extendr-api", 274 | ] 275 | 276 | [[package]] 277 | name = "autocfg" 278 | version = "1.1.0" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 281 | 282 | [[package]] 283 | name = "base64" 284 | version = "0.21.5" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" 287 | 288 | [[package]] 289 | name = "bitflags" 290 | version = "1.3.2" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 293 | 294 | [[package]] 295 | name = "bitflags" 296 | version = "2.4.1" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" 299 | 300 | [[package]] 301 | name = "bumpalo" 302 | version = "3.14.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" 305 | 306 | [[package]] 307 | name = "bytes" 308 | version = "1.5.0" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" 311 | 312 | [[package]] 313 | name = "cc" 314 | version = "1.0.83" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 317 | dependencies = [ 318 | "libc", 319 | ] 320 | 321 | [[package]] 322 | name = "cfg-if" 323 | version = "1.0.0" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 326 | 327 | [[package]] 328 | name = "chrono" 329 | version = "0.4.31" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" 332 | dependencies = [ 333 | "android-tzdata", 334 | "iana-time-zone", 335 | "num-traits", 336 | "windows-targets", 337 | ] 338 | 339 | [[package]] 340 | name = "const-random" 341 | version = "0.1.17" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a" 344 | dependencies = [ 345 | "const-random-macro", 346 | ] 347 | 348 | [[package]] 349 | name = "const-random-macro" 350 | version = "0.1.16" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 353 | dependencies = [ 354 | "getrandom", 355 | "once_cell", 356 | "tiny-keccak", 357 | ] 358 | 359 | [[package]] 360 | name = "core-foundation-sys" 361 | version = "0.8.4" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" 364 | 365 | [[package]] 366 | name = "crunchy" 367 | version = "0.2.2" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 370 | 371 | [[package]] 372 | name = "csv" 373 | version = "1.3.0" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" 376 | dependencies = [ 377 | "csv-core", 378 | "itoa", 379 | "ryu", 380 | "serde", 381 | ] 382 | 383 | [[package]] 384 | name = "csv-core" 385 | version = "0.1.11" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" 388 | dependencies = [ 389 | "memchr", 390 | ] 391 | 392 | [[package]] 393 | name = "equivalent" 394 | version = "1.0.1" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 397 | 398 | [[package]] 399 | name = "extendr-api" 400 | version = "0.6.0" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "c7d55a0174c4df17c467fb59b3f836bec31d1af6d56c4182cfdf34a62d1553a4" 403 | dependencies = [ 404 | "extendr-macros", 405 | "libR-sys", 406 | "once_cell", 407 | "paste", 408 | ] 409 | 410 | [[package]] 411 | name = "extendr-macros" 412 | version = "0.6.0" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "33833971650cade4bfa3097b979506bf2b4934b60392e110f95b94c2406cbb84" 415 | dependencies = [ 416 | "proc-macro2", 417 | "quote", 418 | "syn", 419 | ] 420 | 421 | [[package]] 422 | name = "flatbuffers" 423 | version = "23.5.26" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "4dac53e22462d78c16d64a1cd22371b54cc3fe94aa15e7886a2fa6e5d1ab8640" 426 | dependencies = [ 427 | "bitflags 1.3.2", 428 | "rustc_version", 429 | ] 430 | 431 | [[package]] 432 | name = "getrandom" 433 | version = "0.2.11" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" 436 | dependencies = [ 437 | "cfg-if", 438 | "libc", 439 | "wasi", 440 | ] 441 | 442 | [[package]] 443 | name = "half" 444 | version = "2.3.1" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" 447 | dependencies = [ 448 | "cfg-if", 449 | "crunchy", 450 | "num-traits", 451 | ] 452 | 453 | [[package]] 454 | name = "hashbrown" 455 | version = "0.14.2" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" 458 | 459 | [[package]] 460 | name = "iana-time-zone" 461 | version = "0.1.58" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" 464 | dependencies = [ 465 | "android_system_properties", 466 | "core-foundation-sys", 467 | "iana-time-zone-haiku", 468 | "js-sys", 469 | "wasm-bindgen", 470 | "windows-core", 471 | ] 472 | 473 | [[package]] 474 | name = "iana-time-zone-haiku" 475 | version = "0.1.2" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 478 | dependencies = [ 479 | "cc", 480 | ] 481 | 482 | [[package]] 483 | name = "indexmap" 484 | version = "2.1.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" 487 | dependencies = [ 488 | "equivalent", 489 | "hashbrown", 490 | ] 491 | 492 | [[package]] 493 | name = "itoa" 494 | version = "1.0.9" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" 497 | 498 | [[package]] 499 | name = "js-sys" 500 | version = "0.3.65" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" 503 | dependencies = [ 504 | "wasm-bindgen", 505 | ] 506 | 507 | [[package]] 508 | name = "lazy_static" 509 | version = "1.4.0" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 512 | 513 | [[package]] 514 | name = "lexical-core" 515 | version = "0.8.5" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" 518 | dependencies = [ 519 | "lexical-parse-float", 520 | "lexical-parse-integer", 521 | "lexical-util", 522 | "lexical-write-float", 523 | "lexical-write-integer", 524 | ] 525 | 526 | [[package]] 527 | name = "lexical-parse-float" 528 | version = "0.8.5" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" 531 | dependencies = [ 532 | "lexical-parse-integer", 533 | "lexical-util", 534 | "static_assertions", 535 | ] 536 | 537 | [[package]] 538 | name = "lexical-parse-integer" 539 | version = "0.8.6" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" 542 | dependencies = [ 543 | "lexical-util", 544 | "static_assertions", 545 | ] 546 | 547 | [[package]] 548 | name = "lexical-util" 549 | version = "0.8.5" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" 552 | dependencies = [ 553 | "static_assertions", 554 | ] 555 | 556 | [[package]] 557 | name = "lexical-write-float" 558 | version = "0.8.5" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" 561 | dependencies = [ 562 | "lexical-util", 563 | "lexical-write-integer", 564 | "static_assertions", 565 | ] 566 | 567 | [[package]] 568 | name = "lexical-write-integer" 569 | version = "0.8.5" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" 572 | dependencies = [ 573 | "lexical-util", 574 | "static_assertions", 575 | ] 576 | 577 | [[package]] 578 | name = "libR-sys" 579 | version = "0.6.0" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "a34aaa68a201f71eab5df5a67d1326add8aaf029434e939353bcab0534919ff1" 582 | 583 | [[package]] 584 | name = "libc" 585 | version = "0.2.150" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" 588 | 589 | [[package]] 590 | name = "libm" 591 | version = "0.2.8" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 594 | 595 | [[package]] 596 | name = "log" 597 | version = "0.4.20" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 600 | 601 | [[package]] 602 | name = "memchr" 603 | version = "2.6.4" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 606 | 607 | [[package]] 608 | name = "num" 609 | version = "0.4.1" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" 612 | dependencies = [ 613 | "num-bigint", 614 | "num-complex", 615 | "num-integer", 616 | "num-iter", 617 | "num-rational", 618 | "num-traits", 619 | ] 620 | 621 | [[package]] 622 | name = "num-bigint" 623 | version = "0.4.4" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" 626 | dependencies = [ 627 | "autocfg", 628 | "num-integer", 629 | "num-traits", 630 | ] 631 | 632 | [[package]] 633 | name = "num-complex" 634 | version = "0.4.4" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" 637 | dependencies = [ 638 | "num-traits", 639 | ] 640 | 641 | [[package]] 642 | name = "num-integer" 643 | version = "0.1.45" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 646 | dependencies = [ 647 | "autocfg", 648 | "num-traits", 649 | ] 650 | 651 | [[package]] 652 | name = "num-iter" 653 | version = "0.1.43" 654 | source = "registry+https://github.com/rust-lang/crates.io-index" 655 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 656 | dependencies = [ 657 | "autocfg", 658 | "num-integer", 659 | "num-traits", 660 | ] 661 | 662 | [[package]] 663 | name = "num-rational" 664 | version = "0.4.1" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" 667 | dependencies = [ 668 | "autocfg", 669 | "num-bigint", 670 | "num-integer", 671 | "num-traits", 672 | ] 673 | 674 | [[package]] 675 | name = "num-traits" 676 | version = "0.2.17" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" 679 | dependencies = [ 680 | "autocfg", 681 | "libm", 682 | ] 683 | 684 | [[package]] 685 | name = "once_cell" 686 | version = "1.18.0" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 689 | 690 | [[package]] 691 | name = "paste" 692 | version = "1.0.14" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" 695 | 696 | [[package]] 697 | name = "proc-macro2" 698 | version = "1.0.69" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" 701 | dependencies = [ 702 | "unicode-ident", 703 | ] 704 | 705 | [[package]] 706 | name = "quote" 707 | version = "1.0.33" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 710 | dependencies = [ 711 | "proc-macro2", 712 | ] 713 | 714 | [[package]] 715 | name = "regex" 716 | version = "1.10.2" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" 719 | dependencies = [ 720 | "aho-corasick", 721 | "memchr", 722 | "regex-automata", 723 | "regex-syntax", 724 | ] 725 | 726 | [[package]] 727 | name = "regex-automata" 728 | version = "0.4.3" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" 731 | dependencies = [ 732 | "aho-corasick", 733 | "memchr", 734 | "regex-syntax", 735 | ] 736 | 737 | [[package]] 738 | name = "regex-syntax" 739 | version = "0.8.2" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 742 | 743 | [[package]] 744 | name = "rustc_version" 745 | version = "0.4.0" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 748 | dependencies = [ 749 | "semver", 750 | ] 751 | 752 | [[package]] 753 | name = "ryu" 754 | version = "1.0.15" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" 757 | 758 | [[package]] 759 | name = "semver" 760 | version = "1.0.20" 761 | source = "registry+https://github.com/rust-lang/crates.io-index" 762 | checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" 763 | 764 | [[package]] 765 | name = "serde" 766 | version = "1.0.193" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" 769 | dependencies = [ 770 | "serde_derive", 771 | ] 772 | 773 | [[package]] 774 | name = "serde_derive" 775 | version = "1.0.193" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" 778 | dependencies = [ 779 | "proc-macro2", 780 | "quote", 781 | "syn", 782 | ] 783 | 784 | [[package]] 785 | name = "serde_json" 786 | version = "1.0.108" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" 789 | dependencies = [ 790 | "itoa", 791 | "ryu", 792 | "serde", 793 | ] 794 | 795 | [[package]] 796 | name = "static_assertions" 797 | version = "1.1.0" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 800 | 801 | [[package]] 802 | name = "syn" 803 | version = "2.0.39" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" 806 | dependencies = [ 807 | "proc-macro2", 808 | "quote", 809 | "unicode-ident", 810 | ] 811 | 812 | [[package]] 813 | name = "tiny-keccak" 814 | version = "2.0.2" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 817 | dependencies = [ 818 | "crunchy", 819 | ] 820 | 821 | [[package]] 822 | name = "unicode-ident" 823 | version = "1.0.12" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 826 | 827 | [[package]] 828 | name = "version_check" 829 | version = "0.9.4" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 832 | 833 | [[package]] 834 | name = "wasi" 835 | version = "0.11.0+wasi-snapshot-preview1" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 838 | 839 | [[package]] 840 | name = "wasm-bindgen" 841 | version = "0.2.88" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" 844 | dependencies = [ 845 | "cfg-if", 846 | "wasm-bindgen-macro", 847 | ] 848 | 849 | [[package]] 850 | name = "wasm-bindgen-backend" 851 | version = "0.2.88" 852 | source = "registry+https://github.com/rust-lang/crates.io-index" 853 | checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" 854 | dependencies = [ 855 | "bumpalo", 856 | "log", 857 | "once_cell", 858 | "proc-macro2", 859 | "quote", 860 | "syn", 861 | "wasm-bindgen-shared", 862 | ] 863 | 864 | [[package]] 865 | name = "wasm-bindgen-macro" 866 | version = "0.2.88" 867 | source = "registry+https://github.com/rust-lang/crates.io-index" 868 | checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" 869 | dependencies = [ 870 | "quote", 871 | "wasm-bindgen-macro-support", 872 | ] 873 | 874 | [[package]] 875 | name = "wasm-bindgen-macro-support" 876 | version = "0.2.88" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" 879 | dependencies = [ 880 | "proc-macro2", 881 | "quote", 882 | "syn", 883 | "wasm-bindgen-backend", 884 | "wasm-bindgen-shared", 885 | ] 886 | 887 | [[package]] 888 | name = "wasm-bindgen-shared" 889 | version = "0.2.88" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" 892 | 893 | [[package]] 894 | name = "windows-core" 895 | version = "0.51.1" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" 898 | dependencies = [ 899 | "windows-targets", 900 | ] 901 | 902 | [[package]] 903 | name = "windows-targets" 904 | version = "0.48.5" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 907 | dependencies = [ 908 | "windows_aarch64_gnullvm", 909 | "windows_aarch64_msvc", 910 | "windows_i686_gnu", 911 | "windows_i686_msvc", 912 | "windows_x86_64_gnu", 913 | "windows_x86_64_gnullvm", 914 | "windows_x86_64_msvc", 915 | ] 916 | 917 | [[package]] 918 | name = "windows_aarch64_gnullvm" 919 | version = "0.48.5" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 922 | 923 | [[package]] 924 | name = "windows_aarch64_msvc" 925 | version = "0.48.5" 926 | source = "registry+https://github.com/rust-lang/crates.io-index" 927 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 928 | 929 | [[package]] 930 | name = "windows_i686_gnu" 931 | version = "0.48.5" 932 | source = "registry+https://github.com/rust-lang/crates.io-index" 933 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 934 | 935 | [[package]] 936 | name = "windows_i686_msvc" 937 | version = "0.48.5" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 940 | 941 | [[package]] 942 | name = "windows_x86_64_gnu" 943 | version = "0.48.5" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 946 | 947 | [[package]] 948 | name = "windows_x86_64_gnullvm" 949 | version = "0.48.5" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 952 | 953 | [[package]] 954 | name = "windows_x86_64_msvc" 955 | version = "0.48.5" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 958 | 959 | [[package]] 960 | name = "zerocopy" 961 | version = "0.7.26" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" 964 | dependencies = [ 965 | "zerocopy-derive", 966 | ] 967 | 968 | [[package]] 969 | name = "zerocopy-derive" 970 | version = "0.7.26" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" 973 | dependencies = [ 974 | "proc-macro2", 975 | "quote", 976 | "syn", 977 | ] 978 | -------------------------------------------------------------------------------- /r/src/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = 'arrowextendr' 3 | publish = false 4 | version = '0.1.0' 5 | edition = '2021' 6 | 7 | [lib] 8 | crate-type = [ 'staticlib' ] 9 | name = 'arrowextendr' 10 | 11 | [dependencies] 12 | extendr-api = '*' 13 | arrow_extendr = { path = "/Users/josiahparry/github/arrow-extendr" } 14 | arrow = '*' 15 | -------------------------------------------------------------------------------- /r/src/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | use arrow::array::{Float64Array, ArrayData}; 2 | use arrow::ffi_stream::ArrowArrayStreamReader; 3 | 4 | use arrow_extendr::to::*; 5 | use arrow_extendr::from::*; 6 | use extendr_api::{prelude::*}; 7 | 8 | use arrow::array::Int32Array; 9 | 10 | #[extendr] 11 | /// @export 12 | fn test_i32() -> Result { 13 | 14 | let array = Int32Array::from(vec![Some(1), None, Some(3)]); 15 | array.to_arrow_robj() 16 | } 17 | 18 | #[extendr] 19 | /// @export 20 | fn test_f64() -> Result { 21 | let array = Float64Array::from(vec![Some(1.0), None, Some(3.0)]); 22 | array.to_arrow_robj() 23 | } 24 | 25 | use arrow::datatypes::Field; 26 | use arrow::datatypes::{DataType, TimeUnit}; 27 | 28 | #[extendr] 29 | /// @export 30 | // https://github.com/apache/arrow-rs/blob/200e8c80084442d9579e00967e407cd83191565d/arrow/src/pyarrow.rs#L201 31 | fn test_field() -> Result { 32 | let f = Field::new("field_name", DataType::Binary, true); 33 | f.to_arrow_robj() 34 | } 35 | 36 | 37 | use arrow::{datatypes::Schema, record_batch::RecordBatch}; 38 | use std::sync::Arc; 39 | 40 | #[extendr] 41 | /// @export 42 | fn test_record_batch() -> Result{ 43 | let id_array = Int32Array::from(vec![1, 2, 3, 4, 5]); 44 | let schema = Schema::new(vec![ 45 | Field::new("id", DataType::Int32, false) 46 | ]); 47 | 48 | let batch = RecordBatch::try_new( 49 | Arc::new(schema), 50 | vec![Arc::new(id_array)] 51 | ).unwrap(); 52 | 53 | batch.to_arrow_robj() 54 | } 55 | 56 | #[extendr] 57 | /// @export 58 | fn test_schema() -> Result { 59 | let field_a = Field::new("a", DataType::Date64, false); 60 | let field_b = Field::new("a", DataType::Int64, true); 61 | let field_c = Field::new("b", DataType::Boolean, false); 62 | 63 | let schema = Schema::new(vec![field_a, field_b, field_c]); 64 | schema.to_arrow_robj() 65 | } 66 | 67 | #[extendr] 68 | /// @export 69 | fn test_datatype() -> Result { 70 | let dt = DataType::Timestamp(TimeUnit::Second, None); 71 | dt.to_arrow_robj() 72 | } 73 | 74 | // From testing 75 | #[extendr] 76 | /// @export 77 | fn test_from_field(field: Robj) { 78 | let f = Field::from_arrow_robj(&field); 79 | rprintln!("{:#?}", f); 80 | } 81 | 82 | #[extendr] 83 | /// @export 84 | fn test_from_datatype(field: Robj) { 85 | let f = DataType::from_arrow_robj(&field); 86 | rprintln!("{:#?}", f); 87 | } 88 | 89 | #[extendr] 90 | /// @export 91 | fn test_from_schema(field: Robj) { 92 | let f = Schema::from_arrow_robj(&field); 93 | rprintln!("{:#?}", f); 94 | } 95 | 96 | #[extendr] 97 | /// @export 98 | fn test_from_array(field: Robj) { 99 | let f = ArrayData::from_arrow_robj(&field); 100 | rprintln!("{:#?}", f); 101 | } 102 | 103 | #[extendr] 104 | /// @export 105 | fn test_from_recordbatch(rb: Robj) { 106 | let rb = RecordBatch::from_arrow_robj(&rb).unwrap(); 107 | 108 | rprintln!("{:#?}", rb); 109 | 110 | } 111 | 112 | #[extendr] 113 | /// @export 114 | fn test_from_array_steam_reader(rb: Robj) { 115 | let rb = ArrowArrayStreamReader::from_arrow_robj(&rb).unwrap(); 116 | 117 | rprintln!("Processing ArrowArrayStreamReader..."); 118 | for chunk in rb { 119 | rprintln!("Found {} rows", chunk.unwrap().num_rows()); 120 | } 121 | } 122 | 123 | #[extendr] 124 | /// @export 125 | fn process_stream(stream: Robj) -> i32 { 126 | let rb = ArrowArrayStreamReader::from_arrow_robj(&stream) 127 | .unwrap(); 128 | 129 | let mut n = 0; 130 | 131 | rprintln!("Processing `ArrowArrayStreamReader`..."); 132 | for chunk in rb { 133 | let chunk_rows = chunk.unwrap().num_rows(); 134 | rprintln!("Found {chunk_rows} rows"); 135 | n += chunk_rows as i32; 136 | } 137 | 138 | n 139 | } 140 | 141 | // Macro to generate exports. 142 | // This ensures exported functions are registered with R. 143 | // See corresponding C code in `entrypoint.c`. 144 | extendr_module! { 145 | mod arrowextendr; 146 | fn test_i32; 147 | fn test_f64; 148 | fn test_field; 149 | fn test_record_batch; 150 | fn test_schema; 151 | fn test_datatype; 152 | 153 | // FromArrowRobj impls 154 | fn test_from_field; 155 | fn test_from_datatype; 156 | fn test_from_schema; 157 | fn test_from_array; 158 | fn test_from_recordbatch; 159 | fn test_from_array_steam_reader; 160 | 161 | // 162 | fn process_stream; 163 | } 164 | -------------------------------------------------------------------------------- /src/from.rs: -------------------------------------------------------------------------------- 1 | //! Create arrow-rs objects from an `Robj` 2 | //! 3 | //! ```ignore 4 | //! fn array_from_r(field: Robj) -> Result { 5 | //! ArrayData::from_arrow_robj(&field)? 6 | //! } 7 | //! ``` 8 | //! 9 | //! `Robj`s from `{nanoarrow}` and `{arrow}` are both supported. 10 | //! 11 | //! | arrow-rs struct | R object | 12 | //! | -------------------------| ----------------------------------------------- | 13 | //! | `Field` |`nanoarrow_schema` or `arrow::Field` | 14 | //! | `Schema` |`nanoarrow_schema` or `arrow::Schema` | 15 | //! | `DataType` |`nanoarrow_schema` or `arrow::DataType` | 16 | //! | `ArrayData` |`nanoarrow_array` or `arrow::Array` | 17 | //! | `RecordBatch` |`nanoarrow_array_stream` or `arrow::RecordBatch` | 18 | //! | `ArrowArrayStreamReader` |`nanoarrow_array_stream` | 19 | //! 20 | //! ### Notes 21 | //! 22 | //! In the case of creating a `RecordBatch` from a `nanoarrow_array_stream` only 23 | //! the first chunk is returned. If you expect more than one chunk, use `ArrowArrayStreamReader`. 24 | //! 25 | 26 | use arrow::{ 27 | array::{make_array, ArrayData}, 28 | datatypes::{DataType, Field, Schema}, 29 | error::ArrowError, 30 | ffi::{self, FFI_ArrowArray, FFI_ArrowSchema}, 31 | ffi_stream::{self, ArrowArrayStreamReader, FFI_ArrowArrayStream}, 32 | record_batch::RecordBatch, 33 | }; 34 | 35 | use extendr_api::prelude::*; 36 | use std::result::Result; 37 | 38 | /// Creates arrow-rs Structs from an Robj 39 | /// 40 | 41 | pub trait FromArrowRobj: Sized { 42 | fn from_arrow_robj(robj: &Robj) -> Result; 43 | } 44 | 45 | pub type ErrArrowRobj = ArrowError; 46 | 47 | /// Calls `nanoarrow::nanoarrow_pointer_addr_chr()` 48 | /// 49 | /// Gets the address of a nanoarrow object as a string `Robj` 50 | /// Requires `{nanoarrow}` to be installed. 51 | pub fn nanoarrow_addr(robj: &Robj) -> Result { 52 | R!("nanoarrow::nanoarrow_pointer_addr_chr") 53 | .expect("`nanoarrow` must be installed") 54 | .as_function() 55 | .expect("`nanoarrow_pointer_addr_ch()` must be available") 56 | .call(pairlist!(robj)) 57 | } 58 | 59 | /// Calls `nanoarrow::nanoarrow_pointer_export()` 60 | /// 61 | /// Exports a nanoarrow pointer from R to C 62 | /// Requires `{nanoarrow}` to be installed. 63 | pub fn nanoarrow_export(source: &Robj, dest: String) -> Result { 64 | R!("nanoarrow::nanoarrow_pointer_export") 65 | .expect("`nanoarrow` must be installed") 66 | .as_function() 67 | .expect("`nanoarrow_pointer_export()` must be available") 68 | .call(pairlist!(source, dest)) 69 | } 70 | 71 | impl FromArrowRobj for Field { 72 | fn from_arrow_robj(robj: &Robj) -> Result { 73 | // handle nanoarrow 74 | if robj.inherits("nanoarrow_schema") { 75 | let c_schema = FFI_ArrowSchema::empty(); 76 | let c_schema_ptr = &c_schema as *const FFI_ArrowSchema as usize; 77 | 78 | let _ = nanoarrow_export(robj, c_schema_ptr.to_string()); 79 | 80 | let field = Field::try_from(&c_schema)?; 81 | 82 | return Ok(field); 83 | } 84 | 85 | let is_field = robj.inherits("Field"); 86 | 87 | if !(is_field) { 88 | return Err(ErrArrowRobj::ParseError( 89 | "did not find a `Field` or `nanoarrow_schema`".into(), 90 | )); 91 | } 92 | 93 | let export_to_c = robj 94 | .dollar("export_to_c") 95 | .expect("export_to_c() method to be available") 96 | .as_function() 97 | .unwrap(); 98 | 99 | let c_schema = FFI_ArrowSchema::empty(); 100 | let c_schema_ptr = &c_schema as *const FFI_ArrowSchema as usize; 101 | 102 | let _ = export_to_c.call(pairlist!(c_schema_ptr.to_string())); 103 | let field = Field::try_from(&c_schema)?; 104 | 105 | Ok(field) 106 | } 107 | } 108 | 109 | impl FromArrowRobj for DataType { 110 | fn from_arrow_robj(robj: &Robj) -> Result { 111 | if robj.inherits("nanoarrow_schema") { 112 | let c_schema = FFI_ArrowSchema::empty(); 113 | let c_schema_ptr = &c_schema as *const FFI_ArrowSchema as usize; 114 | 115 | let _ = nanoarrow_export(robj, c_schema_ptr.to_string()); 116 | 117 | let field = DataType::try_from(&c_schema)?; 118 | 119 | return Ok(field); 120 | } 121 | 122 | let is_datatype = robj.inherits("DataType"); 123 | 124 | if !(is_datatype) { 125 | return Err(ErrArrowRobj::ParseError( 126 | "did not find a `DataType` or `nanoarrow_schema`".into(), 127 | )); 128 | } 129 | 130 | let export_to_c = robj 131 | .dollar("export_to_c") 132 | .expect("export_to_c() method to be available") 133 | .as_function() 134 | .unwrap(); 135 | 136 | let c_schema = FFI_ArrowSchema::empty(); 137 | let c_schema_ptr = &c_schema as *const FFI_ArrowSchema as usize; 138 | 139 | let _ = export_to_c.call(pairlist!(c_schema_ptr.to_string())); 140 | let data_type = DataType::try_from(&c_schema)?; 141 | 142 | Ok(data_type) 143 | } 144 | } 145 | 146 | impl FromArrowRobj for Schema { 147 | fn from_arrow_robj(robj: &Robj) -> Result { 148 | if robj.inherits("nanoarrow_schema") { 149 | let c_schema = FFI_ArrowSchema::empty(); 150 | let c_schema_ptr = &c_schema as *const FFI_ArrowSchema as usize; 151 | 152 | let _ = nanoarrow_export(robj, c_schema_ptr.to_string()); 153 | 154 | let field = Schema::try_from(&c_schema)?; 155 | 156 | return Ok(field); 157 | } 158 | 159 | let is_schema = robj.inherits("Schema"); 160 | 161 | if !(is_schema) { 162 | return Err(ErrArrowRobj::ParseError( 163 | "did not find a `Schema` or `nanoarrow_schema`".into(), 164 | )); 165 | } 166 | 167 | let export_to_c = robj 168 | .dollar("export_to_c") 169 | .expect("export_to_c() method to be available") 170 | .as_function() 171 | .unwrap(); 172 | 173 | let c_schema = FFI_ArrowSchema::empty(); 174 | let c_schema_ptr = &c_schema as *const FFI_ArrowSchema as usize; 175 | 176 | let _ = export_to_c.call(pairlist!(c_schema_ptr.to_string())); 177 | let schema = Schema::try_from(&c_schema)?; 178 | 179 | Ok(schema) 180 | } 181 | } 182 | 183 | // https://github.com/apache/arrow-rs/blob/200e8c80084442d9579e00967e407cd83191565d/arrow/src/pyarrow.rs#L248 184 | impl FromArrowRobj for ArrayData { 185 | fn from_arrow_robj(robj: &Robj) -> Result { 186 | if robj.inherits("nanoarrow_array") { 187 | let array = FFI_ArrowArray::empty(); 188 | let schema = FFI_ArrowSchema::empty(); 189 | 190 | let c_array_ptr = &array as *const FFI_ArrowArray as usize; 191 | let c_schema_ptr = &schema as *const FFI_ArrowSchema as usize; 192 | 193 | let robj_schema = R!("nanoarrow::infer_nanoarrow_schema") 194 | .unwrap() 195 | .as_function() 196 | .unwrap() 197 | .call(pairlist!(robj)) 198 | .expect("unable to infer nanoarrow schema"); 199 | 200 | let _ = nanoarrow_export(robj, c_array_ptr.to_string()); 201 | let _ = nanoarrow_export(&robj_schema, c_schema_ptr.to_string()); 202 | 203 | return unsafe { ffi::from_ffi(array, &schema) }; 204 | } 205 | 206 | let is_array = robj.inherits("Array"); 207 | 208 | if !is_array { 209 | return Err(ErrArrowRobj::ParseError("did not find a `Array`".into())); 210 | } 211 | 212 | // prepare a pointer to receive the Array struct 213 | let array = FFI_ArrowArray::empty(); 214 | let schema = FFI_ArrowSchema::empty(); 215 | 216 | let c_array_ptr = &array as *const FFI_ArrowArray as usize; 217 | let c_schema_ptr = &schema as *const FFI_ArrowSchema as usize; 218 | 219 | let export_to_c = robj 220 | .dollar("export_to_c") 221 | .expect("export_to_c() method to be available") 222 | .as_function() 223 | .unwrap(); 224 | 225 | let _ = export_to_c.call(pairlist!(c_array_ptr.to_string(), c_schema_ptr.to_string())); 226 | 227 | unsafe { ffi::from_ffi(array, &schema) } 228 | } 229 | } 230 | 231 | /// If there are more than one RecordBatches in the stream, do not use this 232 | /// Use ArrowStreamReader instead 233 | impl FromArrowRobj for RecordBatch { 234 | fn from_arrow_robj(robj: &Robj) -> Result { 235 | if robj.inherits("nanoarrow_array_stream") { 236 | // we need to allocate an empty schema and fetch it from the record batch 237 | let stream = ffi_stream::FFI_ArrowArrayStream::empty(); 238 | let c_stream_ptr = &stream as *const FFI_ArrowArrayStream as usize; 239 | 240 | let _ = nanoarrow_export(robj, c_stream_ptr.to_string()); 241 | 242 | let res = ArrowArrayStreamReader::try_new(stream)?; 243 | let r2 = res.into_iter().map(|xi| xi.unwrap()).nth(0).unwrap(); 244 | 245 | return Ok(r2); 246 | } 247 | 248 | let is_rb = robj.inherits("RecordBatch"); 249 | 250 | if !is_rb { 251 | return Err(ErrArrowRobj::ParseError( 252 | "did not find a `RecordBatch` or `nanoarrow_array_stream`".into(), 253 | )); 254 | } 255 | 256 | // we need to allocate an empty schema and fetch it from the record batch 257 | let array = FFI_ArrowArray::empty(); 258 | let schema = FFI_ArrowSchema::empty(); 259 | 260 | let c_array_ptr = &array as *const FFI_ArrowArray as usize; 261 | let c_schema_ptr = &schema as *const FFI_ArrowSchema as usize; 262 | 263 | let export_to_c = robj 264 | .dollar("export_to_c") 265 | .expect("export_to_c() method to be available") 266 | .as_function() 267 | .unwrap(); 268 | 269 | let _ = export_to_c.call(pairlist!(c_array_ptr.to_string(), c_schema_ptr.to_string())); 270 | 271 | let res = unsafe { ffi::from_ffi(array, &schema)? }; 272 | let schema = Schema::try_from(&schema)?; 273 | 274 | let res_arrays = res 275 | .child_data() 276 | .into_iter() 277 | .map(|xi| make_array(xi.clone())) 278 | .collect::>(); 279 | 280 | let res = RecordBatch::try_new(schema.into(), res_arrays)?; 281 | 282 | Ok(res) 283 | } 284 | } 285 | 286 | impl FromArrowRobj for ArrowArrayStreamReader { 287 | fn from_arrow_robj(robj: &Robj) -> Result { 288 | // TODO arrow::RecordBatchStreamWriter 289 | if !robj.inherits("nanoarrow_array_stream") { 290 | return Err(ErrArrowRobj::ParseError( 291 | "did not find `nanoarrow_array_stream`".into(), 292 | )); 293 | } 294 | // we need to allocate an empty schema and fetch it from the record batch 295 | let stream = ffi_stream::FFI_ArrowArrayStream::empty(); 296 | let c_stream_ptr = &stream as *const FFI_ArrowArrayStream as usize; 297 | 298 | let _ = nanoarrow_export(robj, c_stream_ptr.to_string()); 299 | 300 | ArrowArrayStreamReader::try_new(stream) 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Pass arrow-rs objects to and from an R session 2 | //! 3 | //! ## Motivating Example 4 | //! 5 | //! Say we have the following `DBI` connection which we will send requests to using arrow. 6 | //! The result of `dbGetQueryArrow()` is a `nanoarrow_array_stream`. We want to 7 | //! count the number of rows in each batch of the steam using Rust. 8 | //! 9 | //! ```r 10 | //! # adapted from https://github.com/r-dbi/DBI/blob/main/vignettes/DBI-arrow.Rmd 11 | //! 12 | //! library(DBI) 13 | //! con <- dbConnect(RSQLite::SQLite()) 14 | //! data <- data.frame( 15 | //! a = runif(10000, 0, 10), 16 | //! b = rnorm(10000, 4.5), 17 | //! c = sample(letters, 10000, TRUE) 18 | //! ) 19 | //! 20 | //! dbWriteTable(con, "tbl", data) 21 | //! ``` 22 | //! 23 | //! We can write an extendr function which creates an `ArrowArrayStreamReader` 24 | //! from an `&Robj`. In the function we instantiate a counter to keep track 25 | //! of the number of rows per chunk. For each chunk we print the number of rows. 26 | //! 27 | //! ```ignore 28 | //! #[extendr] 29 | //! /// @export 30 | //! fn process_stream(stream: Robj) -> i32 { 31 | //! let rb = ArrowArrayStreamReader::from_arrow_robj(&stream) 32 | //! .unwrap(); 33 | //! 34 | //! let mut n = 0; 35 | //! 36 | //! rprintln!("Processing `ArrowArrayStreamReader`..."); 37 | //! for chunk in rb { 38 | //! let chunk_rows = chunk.unwrap().num_rows(); 39 | //! rprintln!("Found {chunk_rows} rows"); 40 | //! n += chunk_rows as i32; 41 | //! } 42 | //! 43 | //! n 44 | //! } 45 | //! ``` 46 | //! 47 | //! With this function we can use it on the output of `dbGetQueryArrow()` or other Arrow 48 | //! related DBI functions. 49 | //! 50 | //! ```r 51 | //! query <- dbGetQueryArrow(con, "SELECT * FROM tbl WHERE a < 3") 52 | //! process_stream(query) 53 | //! #> Processing `ArrowArrayStreamReader`... 54 | //! #> Found 256 rows 55 | //! #> Found 256 rows 56 | //! #> Found 256 rows 57 | //! #> ... truncated ... 58 | //! #> Found 256 rows 59 | //! #> Found 256 rows 60 | //! #> Found 143 rows 61 | //! #> [1] 2959 62 | //! ``` 63 | pub mod from; 64 | pub mod to; 65 | -------------------------------------------------------------------------------- /src/to.rs: -------------------------------------------------------------------------------- 1 | //! Convert arrow-rs structs into an `Robj` 2 | //! 3 | //! The traits `ToArrowRobj` and `IntoArrowRobj` provide the methods 4 | //! `to_arrow_robj()` and `into_arrow_robj()` respectively. The former 5 | //! takes a reference to self whereas the latter consumes self. 6 | //! 7 | //! Prefer `to_arrow_robj()` for all structs except `ArrowArrayStreamReader`. 8 | //! 9 | //! ```ignore 10 | //! fn array_to_robj() -> Result { 11 | //! let array = Int32Array::from(vec![Some(1), None, Some(3)]); 12 | //! array.to_arrow_robj() 13 | //! } 14 | //! ``` 15 | //! 16 | //! | arrow-rs struct | R object | 17 | //! | -------------------------| ----------------------- | 18 | //! | `ArrayData` |`nanoarrow_array` | 19 | //! | `PrimitiveArray` |`nanoarrow_array` | 20 | //! | `Field` |`nanoarrow_schema` | 21 | //! | `DataType` |`nanoarrow_schema` | 22 | //! | `Schema` |`nanoarrow_schema` | 23 | //! | `RecordBatch` |`nanoarrow_array_stream` | 24 | //! | `ArrowArrayStreamReader` |`nanoarrow_array_stream` | 25 | //! 26 | use arrow::{ 27 | array::{Array, ArrayData, PrimitiveArray}, 28 | datatypes::{ArrowPrimitiveType, DataType, Field, Schema, SchemaBuilder}, 29 | error::ArrowError, 30 | ffi::{to_ffi, FFI_ArrowArray, FFI_ArrowSchema}, 31 | ffi_stream::{ArrowArrayStreamReader, FFI_ArrowArrayStream}, 32 | record_batch::{RecordBatch, RecordBatchIterator, RecordBatchReader}, 33 | }; 34 | use extendr_api::prelude::*; 35 | 36 | /// Calls `nanoarrow::nanoarrow_allocate_array()` 37 | /// 38 | /// Requires `{nanoarrow}` to be installed. 39 | pub fn allocate_array(args: Pairlist) -> Result { 40 | R!("nanoarrow::nanoarrow_allocate_array") 41 | .expect("`nanoarrow` must be installed") 42 | .as_function() 43 | .expect("`nanoarrow_allocate_array()` must be available") 44 | .call(args) 45 | } 46 | 47 | /// Calls `nanoarrow::nanoarrow_allocate_array_stream()` 48 | /// 49 | /// Requires `{nanoarrow}` to be installed. 50 | pub fn allocate_array_stream(args: Pairlist) -> Result { 51 | R!("nanoarrow::nanoarrow_allocate_array_stream") 52 | .expect("`nanoarrow` must be installed") 53 | .as_function() 54 | .expect("`nanoarrow_allocate_array()` must be available") 55 | .call(args) 56 | } 57 | 58 | /// Calls `nanoarrow::nanoarrow_allocate_schema()` 59 | /// 60 | /// Requires `{nanoarrow}` to be installed. 61 | pub fn allocate_schema(args: Pairlist) -> Result { 62 | R!("nanoarrow::nanoarrow_allocate_schema") 63 | .expect("`nanoarrow` must be installed") 64 | .as_function() 65 | .expect("`nanoarrow_allocate_schema()` must be available") 66 | .call(args) 67 | } 68 | 69 | /// Calls `nanoarrow::nanoarrow_pointer_move()` 70 | /// 71 | /// Requires `{nanoarrow}` to be installed. 72 | pub fn move_pointer(args: Pairlist) -> Result { 73 | R!("nanoarrow::nanoarrow_pointer_move") 74 | .expect("`nanoarrow` must be installed") 75 | .as_function() 76 | .expect("`nanoarrow_pointer_move()` must be available") 77 | .call(args) 78 | } 79 | 80 | /// Calls `nanoarrow::nanoarrow_array_set_schema()` 81 | /// 82 | /// Requires `{nanoarrow}` to be installed. 83 | pub fn set_array_schema(arr: &Robj, schema: &Robj) { 84 | let _ = R!("nanoarrow::nanoarrow_array_set_schema") 85 | .expect("`nanoarrow` must be installed") 86 | .as_function() 87 | .expect("`nanoarrow_array_set_schema()` must be available") 88 | .call(pairlist!(arr, schema)); 89 | } 90 | 91 | /// Convert an Arrow struct to an `Robj` 92 | /// 93 | /// Does not consume `self`. Takes an arrow-rs struct and converts it into 94 | /// a `{nanoarrow}` S3 object of class `nanoarrow_array`, `nanoarrow_array_stream`, or `nanoarrow_schema`. 95 | /// 96 | /// **Requires `nanoarrow` to be available**. 97 | pub trait ToArrowRobj { 98 | fn to_arrow_robj(&self) -> Result; 99 | } 100 | 101 | impl ToArrowRobj for ArrayData { 102 | fn to_arrow_robj(&self) -> Result { 103 | // take array data and prepare for FFI 104 | let (ffi_array, ffi_schema) = to_ffi(self).expect("success converting arrow data"); 105 | 106 | // extract array pointer. we need it as a string to be used by arrow R package 107 | let ffi_array_ptr = &ffi_array as *const FFI_ArrowArray as usize; 108 | let arry_addr_chr = ffi_array_ptr.to_string(); 109 | 110 | // same deal but with the schema 111 | let ffi_schema_ptr = &ffi_schema as *const FFI_ArrowSchema as usize; 112 | let schema_addr_chr = ffi_schema_ptr.to_string(); 113 | 114 | // allocate empty array and schema 115 | let arr_to_fill = allocate_array(pairlist!())?; 116 | let schema_to_fill = allocate_schema(pairlist!())?; 117 | 118 | // move pointers 119 | let _ = move_pointer(pairlist!(arry_addr_chr, &arr_to_fill)); 120 | let _ = move_pointer(pairlist!(schema_addr_chr, &schema_to_fill)); 121 | 122 | set_array_schema(&arr_to_fill, &schema_to_fill); 123 | 124 | Ok(arr_to_fill) 125 | } 126 | } 127 | 128 | impl ToArrowRobj for PrimitiveArray { 129 | fn to_arrow_robj(&self) -> Result { 130 | let data = self.into_data(); 131 | data.to_arrow_robj() 132 | } 133 | } 134 | 135 | impl ToArrowRobj for Field { 136 | fn to_arrow_robj(&self) -> Result { 137 | let ffi_schema = FFI_ArrowSchema::try_from(self).expect("Field is FFI compatible"); 138 | let ffi_schema_ptr = &ffi_schema as *const FFI_ArrowSchema as usize; 139 | let schema_addr_chr = ffi_schema_ptr.to_string(); 140 | 141 | // allocate the schema 142 | let schema_to_fill = allocate_schema(pairlist!())?; 143 | 144 | // fill the schema with the FFI_ArrowSchema 145 | let _ = move_pointer(pairlist!(schema_addr_chr, &schema_to_fill)); 146 | 147 | Ok(schema_to_fill) 148 | } 149 | } 150 | 151 | impl ToArrowRobj for Schema { 152 | fn to_arrow_robj(&self) -> Result { 153 | let ffi_schema = FFI_ArrowSchema::try_from(self).expect("valid Schema"); 154 | 155 | // allocate and get pntr address 156 | let ffi_schema_ptr = &ffi_schema as *const FFI_ArrowSchema as usize; 157 | let schema_addr_chr = ffi_schema_ptr.to_string(); 158 | 159 | // allocate the schema 160 | let schema_to_fill = allocate_schema(pairlist!())?; 161 | 162 | // fill the schema with the FFI_ArrowSchema 163 | let _ = move_pointer(pairlist!(schema_addr_chr, &schema_to_fill)); 164 | 165 | Ok(schema_to_fill) 166 | } 167 | } 168 | 169 | impl ToArrowRobj for DataType { 170 | fn to_arrow_robj(&self) -> Result { 171 | let ffi_schema = FFI_ArrowSchema::try_from(self).expect("valid Schema"); 172 | 173 | let ffi_schema_ptr = &ffi_schema as *const FFI_ArrowSchema as usize; 174 | let schema_addr_chr = ffi_schema_ptr.to_string(); 175 | 176 | // allocate the schema 177 | let schema_to_fill = allocate_schema(pairlist!())?; 178 | 179 | // fill the schema with the FFI_ArrowSchema 180 | let _ = move_pointer(pairlist!(schema_addr_chr, &schema_to_fill)); 181 | 182 | Ok(schema_to_fill) 183 | } 184 | } 185 | 186 | impl ToArrowRobj for RecordBatch { 187 | fn to_arrow_robj(&self) -> Result { 188 | let reader = RecordBatchIterator::new(vec![Ok(self.clone())], self.schema().clone()); 189 | let reader: Box = Box::new(reader); 190 | let mut stream = FFI_ArrowArrayStream::new(reader); 191 | let stream_ptr = (&mut stream) as *mut FFI_ArrowArrayStream as usize; 192 | 193 | let stream_to_fill = allocate_array_stream(pairlist!())?; 194 | let _ = move_pointer(pairlist!(stream_ptr.to_string(), &stream_to_fill)); 195 | 196 | Ok(stream_to_fill) 197 | } 198 | } 199 | 200 | /// Convert an Arrow struct to an `Robj` 201 | /// 202 | /// Consumes `self`. Takes an arrow-rs struct and converts it into 203 | /// a `{nanoarrow}` S3 object of class `nanoarrow_array`, `nanoarrow_array_stream`, or `nanoarrow_schema`. 204 | /// 205 | /// **Requires `nanoarrow` to be available**. 206 | pub trait IntoArrowRobj { 207 | fn into_arrow_robj(self) -> Result; 208 | } 209 | 210 | // macro to implement `IntoArrowRobj` for those that have `ToArrowRobj` implemented 211 | macro_rules! impl_into_arrow { 212 | ($t:ident) => { 213 | impl IntoArrowRobj for $t { 214 | fn into_arrow_robj(self) -> Result { 215 | self.to_arrow_robj() 216 | } 217 | } 218 | }; 219 | } 220 | 221 | impl_into_arrow!(ArrayData); 222 | impl_into_arrow!(Field); 223 | impl_into_arrow!(Schema); 224 | impl_into_arrow!(DataType); 225 | impl_into_arrow!(RecordBatch); 226 | 227 | // macro doesn't permit generics 228 | impl IntoArrowRobj for PrimitiveArray { 229 | fn into_arrow_robj(self) -> Result { 230 | self.to_arrow_robj() 231 | } 232 | } 233 | 234 | /// Function that will take an ArrowArrayStreamReader and turn into Robj 235 | fn to_arrow_robj_stream_reader(reader: ArrowArrayStreamReader) -> Result { 236 | let reader: Box = Box::new(reader); 237 | let mut stream = FFI_ArrowArrayStream::new(reader); 238 | let stream_ptr = (&mut stream) as *mut FFI_ArrowArrayStream as usize; 239 | 240 | let stream_to_fill = allocate_array_stream(pairlist!())?; 241 | let _ = move_pointer(pairlist!(stream_ptr.to_string(), &stream_to_fill)); 242 | 243 | Ok(stream_to_fill) 244 | } 245 | 246 | impl IntoArrowRobj for ArrowArrayStreamReader { 247 | fn into_arrow_robj(self) -> Result { 248 | to_arrow_robj_stream_reader(self) 249 | } 250 | } 251 | 252 | impl IntoArrowRobj for Box { 253 | fn into_arrow_robj(self) -> Result { 254 | let mut stream = FFI_ArrowArrayStream::new(self); 255 | let stream_ptr = (&mut stream) as *mut FFI_ArrowArrayStream as usize; 256 | 257 | let stream_to_fill = allocate_array_stream(pairlist!())?; 258 | let _ = move_pointer(pairlist!(stream_ptr.to_string(), &stream_to_fill)); 259 | 260 | Ok(stream_to_fill) 261 | } 262 | } 263 | 264 | impl IntoArrowRobj for Vec { 265 | fn into_arrow_robj(self) -> Result { 266 | // if there is an empty vector we create an empty RecordBatch 267 | if self.is_empty() { 268 | let sb = SchemaBuilder::new(); 269 | let schema = sb.finish(); 270 | let empty_iter = vec![].into_iter(); 271 | let rb = arrow::record_batch::RecordBatchIterator::new(empty_iter, schema.into()); 272 | return rb.into_arrow_robj(); 273 | } 274 | 275 | let schema = self[0].schema(); 276 | 277 | let res = self.into_iter().map(Ok::); 278 | 279 | let rbit = arrow::record_batch::RecordBatchIterator::new(res, schema); 280 | 281 | let reader: Box = Box::new(rbit); 282 | 283 | reader.into_arrow_robj() 284 | } 285 | } 286 | 287 | impl IntoArrowRobj for RecordBatchIterator 288 | where 289 | I: IntoIterator> + Send + 'static, 290 | ::IntoIter: Send, 291 | { 292 | fn into_arrow_robj(self) -> Result { 293 | let reader: Box = Box::new(self); 294 | reader.into_arrow_robj() 295 | } 296 | } 297 | --------------------------------------------------------------------------------