Skip to content

Commit 849d445

Browse files
committed
fix action
1 parent e372ecb commit 849d445

6 files changed

Lines changed: 125 additions & 99 deletions

File tree

.github/workflows/docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
runs-on: ubuntu-latest
3131
steps:
3232
- name: Checkout
33-
uses: actions/checkout@v4
33+
uses: actions/checkout@v6
3434

3535
- uses: dtolnay/rust-toolchain@nightly
3636
if: matrix.config.rust == 'nightly'
@@ -41,7 +41,7 @@ jobs:
4141
RUSTDOCFLAGS: "--enable-index-page -Zunstable-options"
4242

4343
- name: Setup Pages
44-
uses: actions/configure-pages@v8
44+
uses: actions/configure-pages@v6
4545

4646
# As of v1.0.9, upload-pages-artifact action rejects files with incorrect permissions.
4747
# In Rust doc's case, .lock is such a file.

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "arrow_extendr"
3-
version = "58.0.1"
3+
version = "58.0.2"
44
edition = "2024"
55
# matches arrow
66
rust-version = "1.85.0"
@@ -12,6 +12,9 @@ keywords = ["arrow", "extendr", "rstats"]
1212
categories = ["development-tools::ffi"]
1313
include = ["Cargo.toml", "README.md", "src/*"]
1414

15+
[package.metadata.docs.rs]
16+
features = ["geoarrow-08", "polars-53"]
17+
1518
[lib]
1619
crate-type = ["lib", "staticlib"]
1720
name = "arrow_extendr"

README.md

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
1-
# arrow_extendr
1+
# arrow-extendr
22

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).
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/) and [arrow-rs](https://docs.rs/arrow).
44

5-
### Motivating Example
5+
Arrow memory is exchanged via the [Arrow C Data Interface](https://arrow.apache.org/docs/format/CDataInterface.html) using R's `nanoarrow_array`, `nanoarrow_schema`, and `nanoarrow_array_stream` external pointer objects. The [`{nanoarrow}`](https://arrow.apache.org/nanoarrow/0.3.0/r/index.html) R package is **not** required as a dependency of your package.
6+
7+
## Features
8+
9+
| Feature | Description |
10+
| ------- | ----------- |
11+
| `arrow` | Core arrow-rs interop (default) |
12+
| `geoarrow-08` | GeoArrow array support via geoarrow-array 0.8 |
13+
| `polars` | Polars interop, alias for `polars-53` |
14+
| `polars-53` | Polars interop for polars-core 0.53 |
15+
| `polars-51` | Polars interop for polars-core 0.51 |
16+
17+
## Motivating Example
618

719
Say we have the following `DBI` connection which we will send requests to using arrow.
820
The result of `dbGetQueryArrow()` is a `nanoarrow_array_stream`. We want to
9-
count the number of rows in each batch of the steam using Rust.
21+
count the number of rows in each batch of the stream using Rust.
1022

1123
```r
1224
# adapted from https://github.com/r-dbi/DBI/blob/main/vignettes/DBI-arrow.Rmd
@@ -67,6 +79,56 @@ process_stream(query)
6779
#> [1] 2959
6880
```
6981

82+
## GeoArrow interop
83+
84+
arrow-extendr supports [GeoArrow](https://geoarrow.org/) via the `geoarrow-08` feature flag, backed by the [geoarrow-array](https://docs.rs/geoarrow-array) crate.
85+
86+
```toml
87+
arrow_extendr = { version = "58.0.1", features = ["geoarrow-08"] }
88+
geoarrow-array = "0.8"
89+
```
90+
91+
This enables the following conversions between Rust and R's `nanoarrow_array` objects:
92+
93+
| Type | `FromArrowRobj` | `ToArrowRobj` | `IntoArrowRobj` |
94+
| ---- | :-------------: | :-----------: | :-------------: |
95+
| `Arc<dyn GeoArrowArray>` ||||
96+
| `PointArray` ||||
97+
| `LineStringArray` ||||
98+
| `PolygonArray` ||||
99+
| `MultiPointArray` ||||
100+
| `MultiLineStringArray` ||||
101+
| `MultiPolygonArray` ||||
102+
| `GeometryArray` ||||
103+
| `GeometryCollectionArray` ||||
104+
| `RectArray` ||||
105+
| `WkbViewArray` ||||
106+
| `WktViewArray` ||||
107+
108+
### Example: round-trip a GeoArrow array through R
109+
110+
```rust
111+
use extendr_api::prelude::*;
112+
use arrow_extendr::{FromArrowRobj, IntoArrowRobj};
113+
use geoarrow_array::array::PointArray;
114+
115+
#[extendr]
116+
/// @export
117+
fn geoarrow_round_trip(x: Robj) -> extendr_api::Result<Robj> {
118+
let array = PointArray::from_arrow_robj(&x)
119+
.map_err(|e| extendr_api::Error::Other(e.to_string()))?;
120+
array.into_arrow_robj()
121+
}
122+
```
123+
124+
```r
125+
library(geoarrow)
126+
library(wk)
127+
128+
pts <- as_geoarrow_array(xy(c(1, 2, 3), c(4, 5, 6)))
129+
geoarrow_round_trip(pts)
130+
```
131+
70132
## Polars interop
71133

72134
arrow-extendr provides optional interop with [Polars](https://docs.rs/polars) via versioned feature flags. Use the feature that matches your `polars-core` version:
@@ -135,10 +197,10 @@ To use arrow-extendr in an R package first create an R package and make it an ex
135197

136198
```r
137199
usethis::create_package("my_package")
138-
rextendr::use_extendr();
200+
rextendr::use_extendr()
139201
```
140202

141-
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.
203+
arrow-extendr implements all Arrow C Data Interface pointer handling in pure Rust, so the `{nanoarrow}` R package is **not** required as a runtime dependency of your package. The pointer objects (`nanoarrow_array`, `nanoarrow_schema`, `nanoarrow_array_stream`) are standard R external pointers whose class names are set by arrow-extendr directly.
142204

143205
## Versioning
144206

src/geoarrow/mod.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,52 @@
1+
//! Convert [geoarrow-array](https://docs.rs/geoarrow-array) structs to and from an `Robj`
2+
//! via the Arrow C Data Interface.
3+
//!
4+
//! Gated behind the `geoarrow-08` feature flag.
5+
//!
6+
//! All types are exchanged as `nanoarrow_array` R external pointer objects, compatible
7+
//! with the [{geoarrow}](https://geoarrow.github.io/geoarrow-r/) R package.
8+
//!
9+
//! ## Conversions
10+
//!
11+
//! | Type | `FromArrowRobj` | `ToArrowRobj` | `IntoArrowRobj` |
12+
//! | ---- | :-------------: | :-----------: | :-------------: |
13+
//! | `Arc<dyn GeoArrowArray>` | ✓ | ✓ | ✓ |
14+
//! | `PointArray` | ✓ | ✓ | ✓ |
15+
//! | `LineStringArray` | ✓ | ✓ | ✓ |
16+
//! | `PolygonArray` | ✓ | ✓ | ✓ |
17+
//! | `MultiPointArray` | ✓ | ✓ | ✓ |
18+
//! | `MultiLineStringArray` | ✓ | ✓ | ✓ |
19+
//! | `MultiPolygonArray` | ✓ | ✓ | ✓ |
20+
//! | `GeometryArray` | ✓ | ✓ | ✓ |
21+
//! | `GeometryCollectionArray` | ✓ | ✓ | ✓ |
22+
//! | `RectArray` | ✓ | ✓ | ✓ |
23+
//! | `WkbViewArray` | ✓ | ✓ | ✓ |
24+
//! | `WktViewArray` | ✓ | ✓ | ✓ |
25+
//!
26+
//! ## Example
27+
//!
28+
//! ```ignore
29+
//! use extendr_api::prelude::*;
30+
//! use arrow_extendr::{FromArrowRobj, IntoArrowRobj};
31+
//! use geoarrow_array::array::PointArray;
32+
//!
33+
//! #[extendr]
34+
//! /// @export
35+
//! fn geoarrow_round_trip(x: Robj) -> extendr_api::Result<Robj> {
36+
//! let array = PointArray::from_arrow_robj(&x)
37+
//! .map_err(|e| extendr_api::Error::Other(e.to_string()))?;
38+
//! array.into_arrow_robj()
39+
//! }
40+
//! ```
41+
//!
42+
//! ```r
43+
//! library(geoarrow)
44+
//! library(wk)
45+
//!
46+
//! pts <- as_geoarrow_array(xy(c(1, 2, 3), c(4, 5, 6)))
47+
//! geoarrow_round_trip(pts)
48+
//! ```
49+
150
use std::sync::Arc;
251

352
use arrow::{

src/nanoarrow.rs

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,6 @@ use extendr_ffi::{
99
Rf_protect, Rf_unprotect,
1010
};
1111

12-
// nanoarrow::infer_nanoarrow_schema()
13-
// SEXP nanoarrow_c_infer_schema_array(SEXP array_xptr) {
14-
// SEXP maybe_schema_xptr = R_ExternalPtrTag(array_xptr);
15-
// if (Rf_inherits(maybe_schema_xptr, "nanoarrow_schema")) {
16-
// return maybe_schema_xptr;
17-
// } else {
18-
// return R_NilValue;
19-
// }
20-
// }
2112
pub(crate) fn infer_schema_array(x: Robj) -> anyhow::Result<Robj> {
2213
let v = unsafe { Robj::from_sexp(R_ExternalPtrTag(x.get())) };
2314
if v.is_null() | !v.inherits("nanoarrow_schema") {
@@ -122,82 +113,3 @@ pub(crate) fn c_export_array_stream(stream_xptr: &Robj) -> anyhow::Result<FFI_Ar
122113
}
123114
Ok(unsafe { FFI_ArrowArrayStream::from_raw(ptr) })
124115
}
125-
126-
// nanoarrow::nanoarrow_pointer_export()`
127-
// function (ptr_src, ptr_dst)
128-
// {
129-
// if (inherits(ptr_src, "nanoarrow_schema")) {
130-
// .Call(nanoarrow_c_export_schema, ptr_src, ptr_dst)
131-
// }
132-
// else if (inherits(ptr_src, "nanoarrow_array")) {
133-
// .Call(nanoarrow_c_export_array, ptr_src, ptr_dst)
134-
// }
135-
// else if (inherits(ptr_src, "nanoarrow_array_stream")) {
136-
// .Call(nanoarrow_c_export_array_stream, ptr_src, ptr_dst)
137-
// }
138-
// else {
139-
// stop("`ptr_src` must inherit from 'nanoarrow_schema', 'nanoarrow_array', or 'nanoarrow_array_stream'")
140-
// }
141-
// invisible(ptr_dst)
142-
// }
143-
// SEXP nanoarrow_c_export_schema(SEXP schema_xptr, SEXP ptr_dst) {
144-
// struct ArrowSchema* obj_src = nanoarrow_schema_from_xptr(schema_xptr);
145-
// SEXP xptr_dst = PROTECT(nanoarrow_c_pointer(ptr_dst));
146-
147-
// struct ArrowSchema* obj_dst = (struct ArrowSchema*)R_ExternalPtrAddr(xptr_dst);
148-
// if (obj_dst == NULL) {
149-
// Rf_error("`ptr_dst` is a pointer to NULL");
150-
// }
151-
152-
// if (obj_dst->release != NULL) {
153-
// Rf_error("`ptr_dst` is a valid struct ArrowSchema");
154-
// }
155-
156-
// int result = ArrowSchemaDeepCopy(obj_src, obj_dst);
157-
// if (result != NANOARROW_OK) {
158-
// Rf_error("Failed to deep copy struct ArrowSchema");
159-
// }
160-
161-
// UNPROTECT(1);
162-
// return R_NilValue;
163-
// }
164-
165-
// SEXP nanoarrow_c_export_array(SEXP array_xptr, SEXP ptr_dst) {
166-
// SEXP xptr_dst = PROTECT(nanoarrow_c_pointer(ptr_dst));
167-
168-
// struct ArrowArray* obj_dst = (struct ArrowArray*)R_ExternalPtrAddr(xptr_dst);
169-
// if (obj_dst == NULL) {
170-
// Rf_error("`ptr_dst` is a pointer to NULL");
171-
// }
172-
173-
// if (obj_dst->release != NULL) {
174-
// Rf_error("`ptr_dst` is a valid struct ArrowArray");
175-
// }
176-
177-
// array_export(array_xptr, obj_dst);
178-
// UNPROTECT(1);
179-
// return R_NilValue;
180-
// }
181-
182-
// SEXP nanoarrow_c_export_array_stream(SEXP array_stream_xptr, SEXP ptr_dst) {
183-
// SEXP xptr_dst = PROTECT(nanoarrow_c_pointer(ptr_dst));
184-
185-
// struct ArrowArrayStream* obj_dst =
186-
// (struct ArrowArrayStream*)R_ExternalPtrAddr(xptr_dst);
187-
// if (obj_dst == NULL) {
188-
// Rf_error("`ptr_dst` is a pointer to NULL");
189-
// }
190-
191-
// if (obj_dst->release != NULL) {
192-
// Rf_error("`ptr_dst` is a valid struct ArrowArrayStream");
193-
// }
194-
195-
// array_stream_export(array_stream_xptr, obj_dst);
196-
197-
// // Remove SEXP dependencies (if important they are kept alive by array_stream_export)
198-
// R_SetExternalPtrProtected(array_stream_xptr, R_NilValue);
199-
// R_SetExternalPtrTag(array_stream_xptr, R_NilValue);
200-
201-
// UNPROTECT(1);
202-
// return R_NilValue;
203-
// }

0 commit comments

Comments
 (0)