Home

Awesome

The Cargo Framework

The paper Writing R Extensions in Rust complements Writing R Extensions (the official guide for writing R extensions) for those interested in developing R packages using Rust. It highlights idiosyncrasies of R and Rust that must be addressed by any integration and describes how to develop Rust-based packages which comply with the CRAN Repository Policy. The paper introduces the cargo framework, a transparent Rust-based API which wraps commonly-used parts of R's API with minimal overhead and allows a programmer to easily add additional wrappers.

This repository hosts the source of the cargo package on CRAN.

Installation

Install using the remotes package:

install.packages("remotes")
remotes::install_github("dbdahl/cargo-framework/cargo")

Usage

For usage information, please see the paper Writing R Extensions in Rust.

The rustdoc for the roxido crate documents the Rval structure and its functions.

Examples

The following are Rust-based packages on CRAN that were developed using this framework.

Getting Started

Please read the paper Writing R Extensions in Rust for full details but, to get a taste, consider the follow...

Setting up your environment is easy.

cargo::install()

Make a new package named, for example, foo:

cargo::new_package("foo")

Install your new package and try out its myrnorm function:

install.packages("foo", repos=NULL, type="source")
set.seed(1L)
foo::myrnorm(5, 0, 1)
[1] -0.6264538  0.1836433 -0.8356286  1.5952808  0.3295078

Now start hacking away on your new Rust-based package. In particular, some of the more interesting files are listed below. See especially src/rust/src/lib.rs.

foo
├── DESCRIPTION
├── R
│   └── myrnorm.R
└── src
    └── rust
        ├── roxido ...
        └── src
            └── lib.rs

You can browse the documentation of the API for the cargo framework:

cargo::api_documentation("foo")

And, you can extend the framework by editing foo/src/rust/roxido/src/r.rs.

Finally, you can also embed Rust code directly in your R scripts:

euclidean_norm <- cargo::rust_fn(x, '
    let ss = x.slice_double().unwrap().iter().fold(0.0, |s,&z| s + z*z);
    Rval::new(ss.sqrt(), pc)
')

euclidean_norm(rnorm(10))
[1] 3.29764

Notice that if you redefine the euclidean_norm function, the second complication is much faster.

Again, for full details, please read the paper Writing R Extensions in Rust.

Citation

To cite in publications, please use

David B. Dahl (2021), Writing R Extensions in Rust, arXiv:2108.07179 [cs.PL], URL https://arxiv.org/abs/2108.07179.

A BibTeX entry for LaTeX users is

  @Misc{,
    title = {Writing R Extensions in Rust},
    author = {David B. Dahl},
    year = {2021},
    eprint = {2108.07179},
    archiveprefix = {arXiv},
    primaryclass = {cs.PL},
  }

Related Projects