Skip to content

Commit b6c0488

Browse files
committed
maybe wire up conversion
1 parent ea03516 commit b6c0488

File tree

1 file changed

+49
-18
lines changed

1 file changed

+49
-18
lines changed

r/src/materialize.c

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ int nanoarrow_ptype_is_data_frame(SEXP ptype) {
109109
(Rf_xlength(ptype) > 0 && has_attrib_safe(ptype, R_NamesSymbol)));
110110
}
111111

112+
int nanoarrow_ptype_is_nanoarrow_vctr(SEXP ptype) {
113+
return Rf_inherits(ptype, "nanoarrow_vctr");
114+
}
115+
112116
SEXP nanoarrow_materialize_realloc(SEXP ptype, R_xlen_t len) {
113117
SEXP result;
114118

@@ -123,7 +127,27 @@ SEXP nanoarrow_materialize_realloc(SEXP ptype, R_xlen_t len) {
123127
}
124128
}
125129

126-
if (nanoarrow_ptype_is_data_frame(ptype)) {
130+
if (nanoarrow_ptype_is_nanoarrow_vctr(ptype)) {
131+
// The object we return here is one that will accumulate chunks and
132+
// be finalized with a value (rather than being strictly copied into
133+
// after every new chunk is seen).
134+
result = PROTECT(Rf_allocVector(INTSXP, len));
135+
Rf_copyMostAttrib(ptype, result);
136+
137+
// For the purposes of building the list of chunks, chunks is a pairlist
138+
// (it will be converted to a regular list when this converter is finalized)
139+
// Technically the first value here won't be used (this simplifies the
140+
// appending).
141+
SEXP chunks_list = PROTECT(Rf_list1(R_NilValue));
142+
143+
// To start, the chunks list and the end of the chunks list are the same node
144+
SEXP chunks_tail_sym = PROTECT(Rf_install("chunks_tail"));
145+
SEXP chunks_sym = PROTECT(Rf_install("chunks"));
146+
Rf_setAttrib(result, chunks_sym, chunks_list);
147+
Rf_setAttrib(result, chunks_tail_sym, chunks_list);
148+
149+
UNPROTECT(4);
150+
} else if (nanoarrow_ptype_is_data_frame(ptype)) {
127151
R_xlen_t num_cols = Rf_xlength(ptype);
128152
result = PROTECT(Rf_allocVector(VECSXP, num_cols));
129153
for (R_xlen_t i = 0; i < num_cols; i++) {
@@ -208,6 +232,10 @@ static void fill_vec_with_nulls(SEXP x, R_xlen_t offset, R_xlen_t len) {
208232
}
209233

210234
static void copy_vec_into(SEXP x, SEXP dst, R_xlen_t offset, R_xlen_t len) {
235+
if (nanoarrow_ptype_is_nanoarrow_vctr(dst)) {
236+
Rf_error("Can't copy_vec_into() to nanoarrow_vctr");
237+
}
238+
211239
if (nanoarrow_ptype_is_data_frame(dst)) {
212240
if (!nanoarrow_ptype_is_data_frame(x)) {
213241
Rf_error("Expected record-style vctr result but got non-record-style result");
@@ -276,22 +304,26 @@ static int nanoarrow_materialize_nanoarrow_vctr(struct RConverter* converter,
276304
// This is a case where the callee needs ownership, which we can do via a
277305
// shallow copy.
278306
SEXP converter_shelter = R_ExternalPtrProtected(converter_xptr);
279-
280-
// TODO: Check that this SEXP has a lifecycle that is going to work with this
281307
SEXP array_xptr = VECTOR_ELT(converter_shelter, 2);
282308

283309
SEXP array_out_xptr = PROTECT(nanoarrow_array_owning_xptr());
284310
struct ArrowArray* out_array = nanoarrow_output_array_from_xptr(array_xptr);
285311
array_export(array_xptr, out_array);
286312

287-
// Append the chunk to the pairlist
313+
// Get the cached copy of the pairlist node at the end of the current
314+
// chunks list.
288315
SEXP chunks_tail_sym = PROTECT(Rf_install("chunks_tail"));
289316
SEXP chunks_tail = PROTECT(Rf_getAttrib(converter->dst.vec_sexp, chunks_tail_sym));
290317

318+
// Create a length-1 pairlist node containing the chunk
291319
SEXP next_sexp = PROTECT(Rf_cons(array_out_xptr, R_NilValue));
320+
321+
// Append it to the end of the current pairlist
292322
SETCDR(chunks_tail, next_sexp);
293323
UNPROTECT(1);
294324

325+
// Update the cached copy of the pairlist node at the end of the current
326+
// chunks list.
295327
Rf_setAttrib(converter->dst.vec_sexp, chunks_tail_sym, next_sexp);
296328
UNPROTECT(3);
297329

@@ -308,20 +340,19 @@ static int nanoarrow_materialize_other(struct RConverter* converter,
308340
UNPROTECT(1);
309341
}
310342

311-
// A unique situation where we don't want owning external pointers because we know
312-
// these are protected for the duration of our call into R and because we don't want
313-
// the underlying array to be released and invalidate the converter. The R code in
314-
// convert_fallback_other() takes care of ensuring an independent copy with the correct
315-
// offset/length.
316-
SEXP schema_xptr = PROTECT(R_MakeExternalPtr(
317-
(struct ArrowSchema*)converter->schema_view.schema, R_NilValue, R_NilValue));
318-
Rf_setAttrib(schema_xptr, R_ClassSymbol, nanoarrow_cls_schema);
319-
// We do need to set the protected member of the array external pointer to signal that
320-
// it is not an independent array (i.e., force a shallow copy).
321-
SEXP array_xptr = PROTECT(R_MakeExternalPtr(
322-
(struct ArrowArray*)converter->array_view.array, schema_xptr, converter_xptr));
323-
Rf_setAttrib(array_xptr, R_ClassSymbol, nanoarrow_cls_array);
343+
// Special-case the nanoarrow_vctr conversion
344+
if (Rf_inherits(converter->dst.vec_sexp, "nanoarrow_vctr")) {
345+
return nanoarrow_materialize_nanoarrow_vctr(converter, converter_xptr);
346+
}
347+
348+
// We've ensured proper ownership of array_xptr and ensured that its
349+
// schema is set, so we can pass these safely to the R-level
350+
// convert_fallback_other.
351+
SEXP converter_shelter = R_ExternalPtrProtected(converter_xptr);
352+
SEXP array_xptr = VECTOR_ELT(converter_shelter, 2);
324353

354+
// The R code in convert_fallback_other() takes care of ensuring an independent copy
355+
// with the correct offset/length if it is necessary to update them.
325356
SEXP offset_sexp = PROTECT(
326357
Rf_ScalarReal((double)(converter->src.array_view->offset + converter->src.offset)));
327358
SEXP length_sexp = PROTECT(Rf_ScalarReal((double)converter->src.length));
@@ -335,7 +366,7 @@ static int nanoarrow_materialize_other(struct RConverter* converter,
335366
copy_vec_into(result_src, converter->dst.vec_sexp, converter->dst.offset,
336367
converter->dst.length);
337368

338-
UNPROTECT(7);
369+
UNPROTECT(5);
339370
return NANOARROW_OK;
340371
}
341372

0 commit comments

Comments
 (0)