Chapter 6 R Type <-> Rust Type

Let’s look at the code generated by rustrize().

6.0.1 Origin:

pub fn say_hi(a:String)-> String{
    a
}

6.0.2 Generated:

#[no_mangle]
pub extern "C" fn rustr_say_hi(a : SEXP)->SEXP{

 let a_ : String = unwrapr!( String::rnew(a) );
 let res  = say_hi(a_);

 let res_sexp : SEXP = unwrapr!(res.intor());

 return res_sexp;
}

rustr_say_hi takes a SEXP R pointer and then uses String::rnew to convert SEXP to Rust String.

6.0.3 RNew

rnew is from trait RNew:

pub trait RNew where Self: Sized
{
    fn rnew(x: SEXP) -> RResult<Self>;
}

String impl RNew, so we can call String::rnew(SEXP).

impl RNew for String {
    fn rnew(x: SEXP) -> RResult<String> {
        .....
    }
}

And that is all. If you want to use you own awesome Rust type as input for R function. impl RNew for it.

6.0.4 IntoR

#[no_mangle]
pub extern "C" fn rustr_say_hi(a : SEXP)->SEXP{

 let a_ : String = unwrapr!( String::rnew(a) );
 let res  = say_hi(a_);

 let res_sexp : SEXP = unwrapr!(res.intor());

 return res_sexp;
}

From say_hi(a_) we get a String, and then we run res.intor(). String impl IntoR, so we can call res.intor().

pub trait IntoR {
    fn intor(&self) -> RResult<SEXP>;
}

RNew - R type to a new Rust type

IntoR - Rust type to R type

Hope this is simple enough.

If you want to use you own awesome Rust type as output. impl IntoR for it.

6.0.5 Orphan Rule

There is an orphan rule to take care. Only your own Rust type can impl traits from rustr crates.

If you want to impl RNew for Vec<String>, you may not get lucky. But you can create a struct to wrap Vec. Zero-cost abstraction feature of Rust often helps you eliminate the overhead.

6.0.6 RNew IntoR impl Added to rustr Crate?

Create a pull request!

We will consider support some rust crates with feature tag. For example, chrono crate for time.