R to Rust type mapping

extendr is allows us to create a bridge between R and Rust. When writing a function in Rust that is intended to be called from R, it is important that the input types be R types. There are many types of objects in R (almost) all of which are available in extendr via a wrapper struct.

The below lists the extendr structs that wrap R object types. These types can be used as function arguments or return values.

Scalar types

R has no concept of scalar values whereas Rust does. Rust does not have the concept of an NA. As such, we have types to represent scalar values in R. The below is how they are mapped.

R type extendr type Rust type
integer(1) Rint i32
double(1) Rfloat f64
logical(1) Rbool bool
complex(1) Rcplx Complex<f64>
character(1) Rstr String

Vector types

Everything in R is a vector. In Rust, we have to point to R’s owned vector types rather than use Rust’s native Vec collection. These are mapped accordingly:

R type extendr type extendr scalar type C API Type
integer() Integers Rint INTSXP
double() Doubles Rfloat REALSXP
logical() Logicals Rbool LGLSXP
complex() Complexes Rcplx CPLXSXP
character() Strings Rstr STRSXP
raw() Raw &[u8] RAWSXP
list() List Robj VECSXP

Using Rust library types vs R-native types

Whenever possible use the extendr wrapper type. Accepting or returning a Vec<T> requires additional allocations. This will always incur memory usage overhead. In some cases, the overhead will be minimal and tolerable. However, if you can use the Rust type instead, always do.

Other types