% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/extension.R
\name{new_extension_type}
\alias{new_extension_type}
\alias{new_extension_array}
\alias{register_extension_type}
\alias{reregister_extension_type}
\alias{unregister_extension_type}
\title{Extension types}
\usage{
new_extension_type(
  storage_type,
  extension_name,
  extension_metadata = raw(),
  type_class = ExtensionType
)

new_extension_array(storage_array, extension_type)

register_extension_type(extension_type)

reregister_extension_type(extension_type)

unregister_extension_type(extension_name)
}
\arguments{
\item{storage_type}{The \link[=data-type]{data type} of the underlying storage
array.}

\item{extension_name}{The extension name. This should be namespaced using
"dot" syntax (i.e., "some_package.some_type"). The namespace "arrow"
is reserved for extension types defined by the Apache Arrow libraries.}

\item{extension_metadata}{A \code{\link[=raw]{raw()}} or \code{\link[=character]{character()}} vector containing the
serialized version of the type. Character vectors must be length 1 and
are converted to UTF-8 before converting to \code{\link[=raw]{raw()}}.}

\item{type_class}{An \link[R6:R6Class]{R6::R6Class} whose \verb{$new()} class method will be
used to construct a new instance of the type.}

\item{storage_array}{An \link{Array} object of the underlying storage.}

\item{extension_type}{An \link{ExtensionType} instance.}
}
\value{
\itemize{
\item \code{new_extension_type()} returns an \link{ExtensionType} instance according
to the \code{type_class} specified.
\item \code{new_extension_array()} returns an \link{ExtensionArray} whose \verb{$type}
corresponds to \code{extension_type}.
\item \code{register_extension_type()}, \code{unregister_extension_type()}
and \code{reregister_extension_type()} return \code{NULL}, invisibly.
}
}
\description{
Extension arrays are wrappers around regular Arrow \link{Array} objects
that provide some customized behaviour and/or storage. A common use-case
for extension types is to define a customized conversion between an
an Arrow \link{Array} and an R object when the default conversion is slow
or loses metadata important to the interpretation of values in the array.
For most types, the built-in
\link[=vctrs_extension_type]{vctrs extension type} is probably sufficient.
}
\details{
These functions create, register, and unregister \link{ExtensionType}
and \link{ExtensionArray} objects. To use an extension type you will have to:
\itemize{
\item Define an \link[R6:R6Class]{R6::R6Class} that inherits from \link{ExtensionType} and reimplement
one or more methods (e.g., \code{deserialize_instance()}).
\item Make a type constructor function (e.g., \code{my_extension_type()}) that calls
\code{\link[=new_extension_type]{new_extension_type()}} to create an R6 instance that can be used as a
\link[=data-type]{data type} elsewhere in the package.
\item Make an array constructor function (e.g., \code{my_extension_array()}) that
calls \code{\link[=new_extension_array]{new_extension_array()}} to create an \link{Array} instance of your
extension type.
\item Register a dummy instance of your extension type created using
you constructor function using \code{\link[=register_extension_type]{register_extension_type()}}.
}

If defining an extension type in an R package, you will probably want to
use \code{\link[=reregister_extension_type]{reregister_extension_type()}} in that package's \code{\link[=.onLoad]{.onLoad()}} hook
since your package will probably get reloaded in the same R session
during its development and \code{\link[=register_extension_type]{register_extension_type()}} will error if
called twice for the same \code{extension_name}. For an example of an
extension type that uses most of these features, see
\code{\link[=vctrs_extension_type]{vctrs_extension_type()}}.
}
\examples{
# Create the R6 type whose methods control how Array objects are
# converted to R objects, how equality between types is computed,
# and how types are printed.
QuantizedType <- R6::R6Class(
  "QuantizedType",
  inherit = ExtensionType,
  public = list(
    # methods to access the custom metadata fields
    center = function() private$.center,
    scale = function() private$.scale,

    # called when an Array of this type is converted to an R vector
    as_vector = function(extension_array) {
      if (inherits(extension_array, "ExtensionArray")) {
        unquantized_arrow <-
          (extension_array$storage()$cast(float64()) / private$.scale) +
          private$.center

        as.vector(unquantized_arrow)
      } else {
        super$as_vector(extension_array)
      }
    },

    # populate the custom metadata fields from the serialized metadata
    deserialize_instance = function() {
      vals <- as.numeric(strsplit(self$extension_metadata_utf8(), ";")[[1]])
      private$.center <- vals[1]
      private$.scale <- vals[2]
    }
  ),
  private = list(
    .center = NULL,
    .scale = NULL
  )
)

# Create a helper type constructor that calls new_extension_type()
quantized <- function(center = 0, scale = 1, storage_type = int32()) {
  new_extension_type(
    storage_type = storage_type,
    extension_name = "arrow.example.quantized",
    extension_metadata = paste(center, scale, sep = ";"),
    type_class = QuantizedType
  )
}

# Create a helper array constructor that calls new_extension_array()
quantized_array <- function(x, center = 0, scale = 1,
                            storage_type = int32()) {
  type <- quantized(center, scale, storage_type)
  new_extension_array(
    Array$create((x - center) * scale, type = storage_type),
    type
  )
}

# Register the extension type so that Arrow knows what to do when
# it encounters this extension type
reregister_extension_type(quantized())

# Create Array objects and use them!
(vals <- runif(5, min = 19, max = 21))

(array <- quantized_array(
  vals,
  center = 20,
  scale = 2^15 - 1,
  storage_type = int16()
)
)

array$type$center()
array$type$scale()

as.vector(array)
}
