use libR_sys::*;
use std::os::raw;
use std::sync::Once;
macro_rules! cstr_mut {
($s: expr) => {
concat!($s, "\0").as_ptr() as *mut raw::c_char
};
}
static mut R_ERROR_BUF: Vec<u8> = Vec::new();
pub fn unwrap_or_throw<T>(r: Result<T, &'static str>) -> T {
unsafe {
match r {
Err(e) => {
R_ERROR_BUF.clear();
R_ERROR_BUF.extend(e.bytes());
R_ERROR_BUF.push(0);
Rf_error(R_ERROR_BUF.as_slice().as_ptr() as *mut raw::c_char);
unreachable!("");
}
Ok(v) => v,
}
}
}
static START_R: Once = Once::new();
pub fn start_r() {
START_R.call_once(|| {
unsafe {
if cfg!(unix) {
if std::env::var("R_HOME").is_err() {
std::env::set_var("R_HOME", env!("R_HOME"));
}
}
Rf_initialize_R(
3,
[cstr_mut!("R"), cstr_mut!("--slave"), cstr_mut!("--no-save")].as_mut_ptr(),
);
R_CStackLimit = usize::max_value();
setup_Rmainloop();
}
});
}
pub fn end_r() {
unsafe {
R_RunExitFinalizers();
R_CleanTempDir();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_engine() {
start_r();
start_r();
}
}