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")

Reply via email to