diff --git a/DESCRIPTION b/DESCRIPTION index f29a6f4b..5d1ef9f7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -34,6 +34,7 @@ Imports: Rcpp, wk (>= 0.6.0) Suggests: + bit64, testthat (>= 3.0.0), vctrs URL: https://r-spatial.github.io/s2/, https://github.com/r-spatial/s2, https://s2geometry.io/ diff --git a/NAMESPACE b/NAMESPACE index f1213d14..7ed3d7c6 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,6 +12,7 @@ S3method(as.character,s2_cell_union) S3method(as.character,s2_geography) S3method(as.list,s2_cell) S3method(as_s2_cell,character) +S3method(as_s2_cell,integer64) S3method(as_s2_cell,s2_cell) S3method(as_s2_cell,s2_geography) S3method(as_s2_cell,wk_xy) diff --git a/R/s2-cell.R b/R/s2-cell.R index 02a316b4..a307efa3 100644 --- a/R/s2-cell.R +++ b/R/s2-cell.R @@ -88,6 +88,14 @@ as_s2_cell.wk_xy <- function(x, ...) { cpp_s2_cell_from_lnglat(as_s2_lnglat(x)) } +#' @rdname s2_cell +#' @export +as_s2_cell.integer64 <- function(x, ...) { + storage <- unclass(x) + storage[is.na(x)] <- NA_real_ + new_s2_cell(storage) +} + #' @rdname s2_cell #' @export new_s2_cell <- function(x) { @@ -95,6 +103,16 @@ new_s2_cell <- function(x) { structure(x, class = c("s2_cell", "wk_vctr")) } +# registered in zzz.R +as.integer64.s2_cell <- function(x, ...) { + # We store 64-bit integegers the same way bit64 does so we can just set the + # class attribute and propagate NA values in the way that bit64 expects them. + x_is_na <- is.na(x) + class(x) <- "integer64" + x[x_is_na] <- bit64::NA_integer64_ + x +} + #' @export as.character.s2_cell <- function(x, ...) { cpp_s2_cell_to_string(x) diff --git a/R/zzz.R b/R/zzz.R index acd3ba81..a06930ad 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -10,6 +10,8 @@ s3_register("vctrs::vec_restore", cls) s3_register("vctrs::vec_ptype_abbr", cls) } + + s3_register("bit64::as.integer64", "s2_cell") } s3_register <- function(generic, class, method = NULL) { diff --git a/tests/testthat/test-s2-cell.R b/tests/testthat/test-s2-cell.R index 46626911..27a938df 100644 --- a/tests/testthat/test-s2-cell.R +++ b/tests/testthat/test-s2-cell.R @@ -10,6 +10,13 @@ test_that("s2_cell class works", { ) }) +test_that("s2_cell bit64::integer64 support works", { + cells <- c(as_s2_cell(NA_character_), s2_cell_sentinel()) + int64s <- bit64::as.integer64(cells) + expect_identical(int64s, bit64::as.integer64(c(NA, -1))) + expect_identical(as_s2_cell(int64s), cells) +}) + test_that("invalid and sentinel values work as expected", { expect_false(s2_cell_is_valid(s2_cell_sentinel())) expect_false(s2_cell_is_valid(s2_cell_invalid()))