This is an automated email from the ASF dual-hosted git repository.
paleolimbot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-nanoarrow.git
The following commit(s) were added to refs/heads/main by this push:
new 804630d feat(r): Add support for `bit64::integer64()` conversions
(#293)
804630d is described below
commit 804630dfc9c0e9648bfc78881f87092d89ddbedd
Author: Dewey Dunnington <[email protected]>
AuthorDate: Fri Sep 8 13:39:57 2023 -0300
feat(r): Add support for `bit64::integer64()` conversions (#293)
This PR implements support for `bit64::integer64()`. This vctr type is a
mostly lossless representation of a 64-bit (signed) integer that is
helpful for representing very large numbers (or uses like `s2_cell()`
that just need a way to store 64 bits losslessly).
This type isn't part of the default conversions because it requires
`bit64`, which has a few dependencies. It is also not the default
because there are some limitations in R that cause that object type to
behave unintuitively in certain places (e.g., when indexing a vector).
Because `convert_vector()` always accepts a target vector type, users
can (now) override the default behaviour with a safer option if that
matters for their use case.
``` r
library(nanoarrow)
suppressPackageStartupMessages(library(bit64))
(vec <- as.integer64(c(-3:3, NA)))
#> integer64
#> [1] -3 -2 -1 0 1 2 3 <NA>
(array <- as_nanoarrow_array(vec))
#> <nanoarrow_array int64[8]>
#> $ length : int 8
#> $ null_count: int 1
#> $ offset : int 0
#> $ buffers :List of 2
#> ..$ :<nanoarrow_buffer validity<bool>[8][1 b]> `TRUE TRUE TRUE TRUE
TRUE T...`
#> ..$ :<nanoarrow_buffer data<int64>[8][64 b]> `-3.00e+00 -2.00e+00
-1.00e+0...`
#> $ dictionary: NULL
#> $ children : list()
convert_array(array, integer64())
#> integer64
#> [1] -3 -2 -1 0 1 2 3 <NA>
```
<sup>Created on 2023-09-01 with [reprex
v2.0.2](https://reprex.tidyverse.org)</sup>
---
r/DESCRIPTION | 1 +
r/NAMESPACE | 2 +
r/R/as-array.R | 47 +++++++++++++
r/R/convert-array.R | 1 -
r/R/schema.R | 5 ++
r/man/as_nanoarrow_schema.Rd | 4 +-
r/src/convert.c | 2 +
r/src/convert_array.c | 3 +-
r/src/materialize.c | 3 +
r/src/materialize_common.h | 1 +
r/src/materialize_int64.h | 129 ++++++++++++++++++++++++++++++++++
r/tests/testthat/test-as-array.R | 56 +++++++++++++++
r/tests/testthat/test-convert-array.R | 94 +++++++++++++++++++++++++
r/tests/testthat/test-schema.R | 5 ++
14 files changed, 349 insertions(+), 4 deletions(-)
diff --git a/r/DESCRIPTION b/r/DESCRIPTION
index edeab1a..ae8612e 100644
--- a/r/DESCRIPTION
+++ b/r/DESCRIPTION
@@ -24,6 +24,7 @@ URL: https://github.com/apache/arrow-nanoarrow
BugReports: https://github.com/apache/arrow-nanoarrow/issues
Suggests:
arrow (>= 9.0.0),
+ bit64,
blob,
hms,
rlang,
diff --git a/r/NAMESPACE b/r/NAMESPACE
index e563e4e..8152a6a 100644
--- a/r/NAMESPACE
+++ b/r/NAMESPACE
@@ -29,6 +29,7 @@ S3method(as_nanoarrow_array,blob)
S3method(as_nanoarrow_array,default)
S3method(as_nanoarrow_array,difftime)
S3method(as_nanoarrow_array,factor)
+S3method(as_nanoarrow_array,integer64)
S3method(as_nanoarrow_array,nanoarrow_array)
S3method(as_nanoarrow_array,nanoarrow_buffer)
S3method(as_nanoarrow_array,vctrs_unspecified)
@@ -76,6 +77,7 @@ S3method(infer_nanoarrow_schema,double)
S3method(infer_nanoarrow_schema,factor)
S3method(infer_nanoarrow_schema,hms)
S3method(infer_nanoarrow_schema,integer)
+S3method(infer_nanoarrow_schema,integer64)
S3method(infer_nanoarrow_schema,logical)
S3method(infer_nanoarrow_schema,nanoarrow_array)
S3method(infer_nanoarrow_schema,nanoarrow_array_stream)
diff --git a/r/R/as-array.R b/r/R/as-array.R
index b26cad8..8a12147 100644
--- a/r/R/as-array.R
+++ b/r/R/as-array.R
@@ -74,12 +74,54 @@ as_nanoarrow_array.nanoarrow_array <- function(x, ...,
schema = NULL) {
NextMethod()
}
+#' @export
+as_nanoarrow_array.integer64 <- function(x, ..., schema = NULL) {
+ if (is.null(schema)) {
+ schema <- infer_nanoarrow_schema(x)
+ }
+
+ schema <- as_nanoarrow_schema(schema)
+ parsed <- nanoarrow_schema_parse(schema)
+ if (!is.null(parsed$extension_name)) {
+ spec <- resolve_nanoarrow_extension(parsed$extension_name)
+ return(as_nanoarrow_array_extension(spec, x, ..., schema = schema))
+ }
+
+ switch(
+ parsed$type,
+ int64 = ,
+ uint64 = {
+ if (anyNA(x)) {
+ is_valid_lgl <- is.finite(x)
+ is_valid <- as_nanoarrow_array(is_valid_lgl, schema =
na_bool())$buffers[[2]]
+ na_count <- length(x) - sum(is_valid_lgl)
+ } else {
+ is_valid <- NULL
+ na_count <- 0
+ }
+
+ array <- nanoarrow_array_init(schema)
+ nanoarrow_array_modify(
+ array,
+ list(
+ length = length(x),
+ null_count = na_count,
+ buffers = list(is_valid, x)
+ )
+ )
+ },
+ as_nanoarrow_array(as.double(x), schema = schema)
+ )
+
+}
+
#' @export
as_nanoarrow_array.POSIXct <- function(x, ..., schema = NULL) {
if (is.null(schema)) {
schema <- infer_nanoarrow_schema(x)
}
+ schema <- as_nanoarrow_schema(schema)
parsed <- nanoarrow_schema_parse(schema)
if (!is.null(parsed$extension_name)) {
spec <- resolve_nanoarrow_extension(parsed$extension_name)
@@ -109,6 +151,7 @@ as_nanoarrow_array.difftime <- function(x, ..., schema =
NULL) {
schema <- infer_nanoarrow_schema(x)
}
+ schema <- as_nanoarrow_schema(schema)
parsed <- nanoarrow_schema_parse(schema)
if (!is.null(parsed$extension_name)) {
spec <- resolve_nanoarrow_extension(parsed$extension_name)
@@ -158,6 +201,7 @@ as_nanoarrow_array.Date <- function(x, ..., schema = NULL) {
schema <- infer_nanoarrow_schema(x)
}
+ schema <- as_nanoarrow_schema(schema)
parsed <- nanoarrow_schema_parse(schema)
if (!is.null(parsed$extension_name)) {
spec <- resolve_nanoarrow_extension(parsed$extension_name)
@@ -192,6 +236,7 @@ as_nanoarrow_array.POSIXlt <- function(x, ..., schema =
NULL) {
schema <- infer_nanoarrow_schema(x)
}
+ schema <- as_nanoarrow_schema(schema)
parsed <- nanoarrow_schema_parse(schema)
if (!is.null(parsed$extension_name)) {
spec <- resolve_nanoarrow_extension(parsed$extension_name)
@@ -207,6 +252,7 @@ as_nanoarrow_array.factor <- function(x, ..., schema =
NULL) {
schema <- infer_nanoarrow_schema(x)
}
+ schema <- as_nanoarrow_schema(schema)
parsed <- nanoarrow_schema_parse(schema)
if (!is.null(parsed$extension_name)) {
spec <- resolve_nanoarrow_extension(parsed$extension_name)
@@ -233,6 +279,7 @@ as_nanoarrow_array.vctrs_unspecified <- function(x, ...,
schema = NULL) {
schema <- as_nanoarrow_schema(schema)
}
+ schema <- as_nanoarrow_schema(schema)
parsed <- nanoarrow_schema_parse(schema)
if (!is.null(parsed$extension_name)) {
spec <- resolve_nanoarrow_extension(parsed$extension_name)
diff --git a/r/R/convert-array.R b/r/R/convert-array.R
index 7077c73..6de82d1 100644
--- a/r/R/convert-array.R
+++ b/r/R/convert-array.R
@@ -208,7 +208,6 @@ convert_array.factor <- function(array, to, ...) {
fct_data
}
-
stop_cant_convert_array <- function(array, to, n = 0) {
stop_cant_convert_schema(infer_nanoarrow_schema(array), to, n - 1)
}
diff --git a/r/R/schema.R b/r/R/schema.R
index 0b70741..4088bd4 100644
--- a/r/R/schema.R
+++ b/r/R/schema.R
@@ -87,6 +87,11 @@ infer_nanoarrow_schema.character <- function(x, ...) {
}
}
+#' @export
+infer_nanoarrow_schema.integer64 <- function(x, ...) {
+ na_int64()
+}
+
#' @export
infer_nanoarrow_schema.factor <- function(x, ...) {
na_dictionary(
diff --git a/r/man/as_nanoarrow_schema.Rd b/r/man/as_nanoarrow_schema.Rd
index db32ff3..20f97f6 100644
--- a/r/man/as_nanoarrow_schema.Rd
+++ b/r/man/as_nanoarrow_schema.Rd
@@ -33,8 +33,8 @@ An object of class 'nanoarrow_schema'
\description{
In nanoarrow a 'schema' refers to a \verb{struct ArrowSchema} as defined in the
Arrow C Data interface. This data structure can be used to represent an
-\code{\link[arrow:schema]{arrow::schema()}}, an
\code{\link[arrow:Field]{arrow::field()}}, or an \code{arrow::DataType}. Note
that
-in nanoarrow, an \code{\link[arrow:schema]{arrow::schema()}} and a
non-nullable \code{\link[arrow:data-type]{arrow::struct()}}
+\code{\link[arrow:Schema]{arrow::schema()}}, an
\code{\link[arrow:Field]{arrow::field()}}, or an \code{arrow::DataType}. Note
that
+in nanoarrow, an \code{\link[arrow:Schema]{arrow::schema()}} and a
non-nullable \code{\link[arrow:data-type]{arrow::struct()}}
are represented identically.
}
\examples{
diff --git a/r/src/convert.c b/r/src/convert.c
index 3b62b80..c0054d7 100644
--- a/r/src/convert.c
+++ b/r/src/convert.c
@@ -250,6 +250,8 @@ SEXP nanoarrow_converter_from_ptype(SEXP ptype) {
} else if (Rf_inherits(ptype, "difftime")) {
converter->ptype_view.vector_type = VECTOR_TYPE_DIFFTIME;
converter->ptype_view.r_time_units = time_units_from_difftime(ptype);
+ } else if (Rf_inherits(ptype, "integer64")) {
+ converter->ptype_view.vector_type = VECTOR_TYPE_INTEGER64;
} else {
converter->ptype_view.vector_type = VECTOR_TYPE_OTHER;
}
diff --git a/r/src/convert_array.c b/r/src/convert_array.c
index 82e2942..375bfa0 100644
--- a/r/src/convert_array.c
+++ b/r/src/convert_array.c
@@ -243,7 +243,8 @@ SEXP nanoarrow_c_convert_array(SEXP array_xptr, SEXP
ptype_sexp) {
Rf_inherits(ptype_sexp, "vctrs_list_of") ||
Rf_inherits(ptype_sexp, "Date") || Rf_inherits(ptype_sexp,
"hms") ||
Rf_inherits(ptype_sexp, "POSIXct") ||
- Rf_inherits(ptype_sexp, "difftime")) {
+ Rf_inherits(ptype_sexp, "difftime") ||
+ Rf_inherits(ptype_sexp, "integer64")) {
return convert_array_default(array_xptr, VECTOR_TYPE_UNINITIALIZED,
ptype_sexp);
} else {
return call_convert_array(array_xptr, ptype_sexp);
diff --git a/r/src/materialize.c b/r/src/materialize.c
index 7804813..b86b54d 100644
--- a/r/src/materialize.c
+++ b/r/src/materialize.c
@@ -33,6 +33,7 @@
#include "materialize_dbl.h"
#include "materialize_difftime.h"
#include "materialize_int.h"
+#include "materialize_int64.h"
#include "materialize_lgl.h"
#include "materialize_posixct.h"
#include "materialize_unspecified.h"
@@ -478,6 +479,8 @@ static int nanoarrow_materialize_base(struct RConverter*
converter, SEXP convert
return nanoarrow_materialize_date(converter);
case VECTOR_TYPE_DIFFTIME:
return nanoarrow_materialize_difftime(converter);
+ case VECTOR_TYPE_INTEGER64:
+ return nanoarrow_materialize_int64(src, dst, options);
case VECTOR_TYPE_BLOB:
return nanoarrow_materialize_blob(src, dst, options);
case VECTOR_TYPE_LIST_OF:
diff --git a/r/src/materialize_common.h b/r/src/materialize_common.h
index 22f74c5..1be73a9 100644
--- a/r/src/materialize_common.h
+++ b/r/src/materialize_common.h
@@ -38,6 +38,7 @@ enum VectorType {
VECTOR_TYPE_POSIXCT,
VECTOR_TYPE_DATE,
VECTOR_TYPE_DIFFTIME,
+ VECTOR_TYPE_INTEGER64,
VECTOR_TYPE_BLOB,
VECTOR_TYPE_LIST_OF,
VECTOR_TYPE_DATA_FRAME,
diff --git a/r/src/materialize_int64.h b/r/src/materialize_int64.h
new file mode 100644
index 0000000..f63617b
--- /dev/null
+++ b/r/src/materialize_int64.h
@@ -0,0 +1,129 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#ifndef R_MATERIALIZE_INT64_H_INCLUDED
+#define R_MATERIALIZE_INT64_H_INCLUDED
+
+#include <R.h>
+#include <Rinternals.h>
+
+#include "materialize_common.h"
+#include "nanoarrow.h"
+
+#define NA_INTEGER64 INT64_MIN
+
+static inline int nanoarrow_materialize_int64(struct ArrayViewSlice* src,
+ struct VectorSlice* dst,
+ struct MaterializeOptions*
options) {
+ if (src->array_view->array->dictionary != NULL) {
+ return ENOTSUP;
+ }
+
+ int64_t* result = (int64_t*)REAL(dst->vec_sexp);
+ int64_t n_bad_values = 0;
+
+ // True for all the types supported here
+ const uint8_t* is_valid = src->array_view->buffer_views[0].data.as_uint8;
+ int64_t raw_src_offset = src->array_view->array->offset + src->offset;
+
+ // Fill the buffer
+ switch (src->array_view->storage_type) {
+ case NANOARROW_TYPE_NA:
+ for (R_xlen_t i = 0; i < dst->length; i++) {
+ result[dst->offset + i] = NA_INTEGER64;
+ }
+ break;
+ case NANOARROW_TYPE_INT64:
+ memcpy(result + dst->offset,
+ src->array_view->buffer_views[1].data.as_int32 + raw_src_offset,
+ dst->length * sizeof(int64_t));
+
+ // Set any nulls to NA_INTEGER64
+ if (is_valid != NULL && src->array_view->array->null_count != 0) {
+ for (R_xlen_t i = 0; i < dst->length; i++) {
+ if (!ArrowBitGet(is_valid, raw_src_offset + i)) {
+ result[dst->offset + i] = NA_INTEGER64;
+ }
+ }
+ }
+ break;
+ case NANOARROW_TYPE_BOOL:
+ case NANOARROW_TYPE_INT8:
+ case NANOARROW_TYPE_UINT8:
+ case NANOARROW_TYPE_INT16:
+ case NANOARROW_TYPE_UINT16:
+ case NANOARROW_TYPE_INT32:
+ case NANOARROW_TYPE_UINT32:
+ // No need to bounds check for these types
+ for (R_xlen_t i = 0; i < dst->length; i++) {
+ result[dst->offset + i] =
+ ArrowArrayViewGetIntUnsafe(src->array_view, src->offset + i);
+ }
+
+ // Set any nulls to NA_INTEGER
+ if (is_valid != NULL && src->array_view->array->null_count != 0) {
+ for (R_xlen_t i = 0; i < dst->length; i++) {
+ if (!ArrowBitGet(is_valid, raw_src_offset + i)) {
+ result[dst->offset + i] = NA_INTEGER64;
+ }
+ }
+ }
+ break;
+ case NANOARROW_TYPE_UINT64:
+ case NANOARROW_TYPE_FLOAT:
+ case NANOARROW_TYPE_DOUBLE:
+ // Loop + bounds check. Because we don't know what memory might be
+ // in a null slot, we have to check nulls if there are any.
+ if (is_valid != NULL && src->array_view->array->null_count != 0) {
+ for (R_xlen_t i = 0; i < dst->length; i++) {
+ if (ArrowBitGet(is_valid, raw_src_offset + i)) {
+ int64_t value = ArrowArrayViewGetIntUnsafe(src->array_view,
src->offset + i);
+ if (value > INT64_MAX || value <= NA_INTEGER64) {
+ result[dst->offset + i] = NA_INTEGER64;
+ n_bad_values++;
+ } else {
+ result[dst->offset + i] = value;
+ }
+ } else {
+ result[dst->offset + i] = NA_INTEGER64;
+ }
+ }
+ } else {
+ for (R_xlen_t i = 0; i < dst->length; i++) {
+ int64_t value = ArrowArrayViewGetIntUnsafe(src->array_view,
src->offset + i);
+ if (value > INT64_MAX || value <= NA_INTEGER64) {
+ result[dst->offset + i] = NA_INTEGER64;
+ n_bad_values++;
+ } else {
+ result[dst->offset + i] = value;
+ }
+ }
+ }
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ if (n_bad_values > 0) {
+ Rf_warning("%ld value(s) outside integer64 range set to NA",
(long)n_bad_values);
+ }
+
+ return NANOARROW_OK;
+}
+
+#endif
diff --git a/r/tests/testthat/test-as-array.R b/r/tests/testthat/test-as-array.R
index 7ed5cc8..e30c73f 100644
--- a/r/tests/testthat/test-as-array.R
+++ b/r/tests/testthat/test-as-array.R
@@ -197,6 +197,62 @@ test_that("as_nanoarrow_array() works for double() ->
na_int64()", {
expect_identical(convert_array(array), as.double(c(1:10, NA_real_)))
})
+test_that("as_nanoarrow_array() works for integer64() -> na_int32()", {
+ skip_if_not_installed("bit64")
+
+ # Without nulls
+ array <- as_nanoarrow_array(bit64::as.integer64(1:10), schema = na_int32())
+ expect_identical(infer_nanoarrow_schema(array)$format, "i")
+ expect_identical(as.raw(array$buffers[[1]]), raw())
+ expect_identical(array$offset, 0L)
+ expect_identical(array$null_count, 0L)
+ expect_identical(
+ as.raw(array$buffers[[2]]),
+ as.raw(as_nanoarrow_buffer(1:10))
+ )
+
+ # With nulls
+ array <- as_nanoarrow_array(bit64::as.integer64(c(1:10, NA_real_)), schema =
na_int32())
+ expect_identical(infer_nanoarrow_schema(array)$format, "i")
+ expect_identical(array$null_count, 1L)
+ expect_identical(
+ as.raw(array$buffers[[1]]),
+ packBits(c(rep(TRUE, 10), FALSE, rep(FALSE, 5)))
+ )
+ # The last element here is 0 because (int)nan is undefined behaviour
+ expect_identical(
+ as.raw(array$buffers[[2]]),
+ as.raw(as_nanoarrow_buffer(c(1:10, 0L)))
+ )
+})
+
+test_that("as_nanoarrow_array() works for integer64() -> na_int64()", {
+ skip_if_not_installed("bit64")
+
+ # Default roundtrip
+ array <- as_nanoarrow_array(bit64::as.integer64(1:10))
+ expect_identical(convert_array(array, double()), as.double(1:10))
+
+ # Without nulls
+ array <- as_nanoarrow_array(bit64::as.integer64(1:10), schema = na_int64())
+ expect_identical(infer_nanoarrow_schema(array)$format, "l")
+ expect_identical(as.raw(array$buffers[[1]]), raw())
+ expect_identical(array$offset, 0L)
+ expect_identical(array$null_count, 0L)
+ # This *is* how we create int64 buffers, so just check the roundtrip
+ expect_identical(convert_array(array, double()), as.double(1:10))
+
+ # With nulls
+ array <- as_nanoarrow_array(bit64::as.integer64(c(1:10, NA_real_)), schema =
na_int64())
+ expect_identical(infer_nanoarrow_schema(array)$format, "l")
+ expect_identical(array$null_count, 1L)
+ expect_identical(
+ as.raw(array$buffers[[1]]),
+ packBits(c(rep(TRUE, 10), FALSE, rep(FALSE, 5)))
+ )
+ expect_identical(convert_array(array, double()), as.double(c(1:10,
NA_real_)))
+})
+
test_that("as_nanoarrow_array() works for double -> na_int8()", {
skip_if_not_installed("arrow")
casted <- as_nanoarrow_array(as.double(1:10), schema = na_int8())
diff --git a/r/tests/testthat/test-convert-array.R
b/r/tests/testthat/test-convert-array.R
index 8d457e0..e2c3994 100644
--- a/r/tests/testthat/test-convert-array.R
+++ b/r/tests/testthat/test-convert-array.R
@@ -530,6 +530,100 @@ test_that("convert to vector errors for bad array to
double()", {
)
})
+test_that("convert to vector works for valid integer64()", {
+ skip_if_not_installed("bit64")
+ skip_if_not_installed("arrow")
+
+ arrow_numeric_types <- list(
+ int8 = arrow::int8(),
+ uint8 = arrow::uint8(),
+ int16 = arrow::int16(),
+ uint16 = arrow::uint16(),
+ int32 = arrow::int32(),
+ uint32 = arrow::uint32(),
+ int64 = arrow::int64(),
+ uint64 = arrow::uint64(),
+ float32 = arrow::float32(),
+ float64 = arrow::float64()
+ )
+
+ vals <- bit64::as.integer64(c(NA, 0:10))
+ for (nm in names(arrow_numeric_types)) {
+ expect_identical(
+ convert_array(
+ as_nanoarrow_array(vals, schema = arrow_numeric_types[[!!nm]]),
+ bit64::integer64()
+ ),
+ vals
+ )
+ }
+
+ vals_no_na <- bit64::as.integer64(0:10)
+ for (nm in names(arrow_numeric_types)) {
+ expect_identical(
+ convert_array(
+ as_nanoarrow_array(vals_no_na, schema = arrow_numeric_types[[!!nm]]),
+ bit64::integer64()
+ ),
+ vals_no_na
+ )
+ }
+
+ # Boolean array to double
+ expect_identical(
+ convert_array(
+ as_nanoarrow_array(c(NA, TRUE, FALSE), schema = arrow::boolean()),
+ bit64::integer64()
+ ),
+ bit64::as.integer64(c(NA, 1L, 0L))
+ )
+
+ expect_identical(
+ convert_array(
+ as_nanoarrow_array(c(TRUE, FALSE), schema = arrow::boolean()),
+ bit64::integer64()
+ ),
+ bit64::as.integer64(c(1L, 0L))
+ )
+})
+
+test_that("convert to vector works for null -> integer64()", {
+ skip_if_not_installed("bit64")
+
+ array <- nanoarrow_array_init(na_na())
+ array$length <- 10
+ array$null_count <- 10
+
+ expect_identical(
+ convert_array(array, bit64::integer64()),
+ rep(bit64::NA_integer64_, 10)
+ )
+})
+
+test_that("convert to vector works for extension<int64> -> integer64()", {
+ skip_if_not_installed("bit64")
+
+ vec <- bit64::as.integer64(c(0, 1, NA))
+ array <- nanoarrow_extension_array(vec, "some_ext")
+
+ expect_warning(
+ expect_identical(
+ convert_array(array, bit64::integer64()),
+ vec
+ ),
+ "Converting unknown extension"
+ )
+})
+
+test_that("convert to vector errors for bad array to integer64()", {
+ skip_if_not_installed("bit64")
+
+ expect_error(
+ convert_array(as_nanoarrow_array(letters), bit64::integer64()),
+ "Can't convert array <string> to R vector of type integer64"
+ )
+})
+
test_that("convert to vector works for character()", {
array <- as_nanoarrow_array(letters)
expect_identical(
diff --git a/r/tests/testthat/test-schema.R b/r/tests/testthat/test-schema.R
index 93e94b0..ee2cbd9 100644
--- a/r/tests/testthat/test-schema.R
+++ b/r/tests/testthat/test-schema.R
@@ -95,6 +95,11 @@ test_that("infer_nanoarrow_schema() methods work for vctrs
types", {
expect_identical(list_schema$children[[1]]$format, "i")
})
+test_that("infer_nanoarrow_schema() method works for integer64()", {
+ skip_if_not_installed("bit64")
+ expect_identical(infer_nanoarrow_schema(bit64::integer64())$format, "l")
+})
+
test_that("nanoarrow_schema_parse() works", {
simple_info <- nanoarrow_schema_parse(na_int32())
expect_identical(simple_info$type, "int32")