use crate::*;
use libR_sys::*;
pub mod character;
pub mod environment;
pub mod expr;
pub mod function;
pub mod lang;
pub mod list;
pub mod matrix;
pub mod nullable;
pub mod pairlist;
pub mod primitive;
pub mod promise;
pub mod raw;
pub mod symbol;
pub use character::Character;
pub use environment::{EnvIter, Environment};
pub use expr::Expression;
pub use function::Function;
pub use lang::Language;
pub use list::{FromList, List, ListIter};
pub use matrix::{RArray, RColumn, RMatrix, RMatrix3D};
pub use nullable::Nullable;
pub use pairlist::{Pairlist, PairlistIter};
pub use primitive::Primitive;
pub use promise::Promise;
pub use raw::Raw;
pub use symbol::Symbol;
pub(crate) fn make_symbol(name: &str) -> SEXP {
let mut bytes = Vec::with_capacity(name.len() + 1);
bytes.extend(name.bytes());
bytes.push(0);
unsafe { Rf_install(bytes.as_ptr() as *const ::std::os::raw::c_char) }
}
pub(crate) fn make_vector<T>(sexptype: u32, values: T) -> Robj
where
T: IntoIterator,
T::IntoIter: ExactSizeIterator,
T::Item: Into<Robj>,
{
single_threaded(|| unsafe {
let values = values.into_iter();
let sexp = Rf_allocVector(sexptype, values.len() as R_xlen_t);
ownership::protect(sexp);
for (i, val) in values.enumerate() {
SET_VECTOR_ELT(sexp, i as R_xlen_t, val.into().get());
}
Robj::Owned(sexp)
})
}
macro_rules! make_conversions {
($typename: ident, $errname: ident, $isfunc: ident, $errstr: expr) => {
impl<'a> FromRobj<'a> for $typename {
fn from_robj(robj: &'a Robj) -> std::result::Result<Self, &'static str> {
if let Ok(f) = $typename::try_from(robj.clone()) {
Ok(f)
} else {
Err($errstr)
}
}
}
impl From<$typename> for Robj {
fn from(val: $typename) -> Self {
val.robj
}
}
impl TryFrom<Robj> for $typename {
type Error = crate::Error;
fn try_from(robj: Robj) -> Result<Self> {
if robj.$isfunc() {
Ok($typename { robj })
} else {
Err(Error::$errname(robj))
}
}
}
impl Deref for $typename {
type Target = Robj;
fn deref(&self) -> &Self::Target {
&self.robj
}
}
};
}
make_conversions!(Pairlist, ExpectedPairlist, is_pairlist, "Not a pairlist");
make_conversions!(Function, ExpectedFunction, is_function, "Not a function");
make_conversions!(Raw, ExpectedRaw, is_raw, "Not a raw object");
make_conversions!(
Character,
ExpectedCharacter,
is_character,
"Not a character object"
);
make_conversions!(
Environment,
ExpectedEnvironment,
is_environment,
"Not an Environment"
);
make_conversions!(List, ExpectedList, is_list, "Not a List");
make_conversions!(
Expression,
ExpectedExpression,
is_expression,
"Not an Expression"
);
make_conversions!(
Language,
ExpectedLanguage,
is_language,
"Not a Language object"
);
make_conversions!(Symbol, ExpectedSymbol, is_symbol, "Not a Symbol object");
make_conversions!(
Primitive,
ExpectedPrimitive,
is_primitive,
"Not a Primitive object"
);
make_conversions!(Promise, ExpectedPromise, is_promise, "Not a Promise object");
impl Robj {
pub fn as_symbol(&self) -> Option<Symbol> {
Symbol::try_from(self.clone()).ok()
}
pub fn as_character(&self) -> Option<Character> {
Character::try_from(self.clone()).ok()
}
pub fn as_raw(&self) -> Option<Raw> {
Raw::try_from(self.clone()).ok()
}
pub fn as_language(&self) -> Option<Language> {
Language::try_from(self.clone()).ok()
}
pub fn as_pairlist(&self) -> Option<Pairlist> {
Pairlist::try_from(self.clone()).ok()
}
pub fn as_list(&self) -> Option<List> {
List::try_from(self.clone()).ok()
}
pub fn as_expression(&self) -> Option<Expression> {
Expression::try_from(self.clone()).ok()
}
pub fn as_environment(&self) -> Option<Environment> {
Environment::try_from(self.clone()).ok()
}
pub fn as_function(&self) -> Option<Function> {
Function::try_from(self.clone()).ok()
}
pub fn as_promise(&self) -> Option<Promise> {
Promise::try_from(self.clone()).ok()
}
}
pub trait SymPair {
fn sym_pair(self) -> (Option<Robj>, Robj);
}
impl<S, R> SymPair for (S, R)
where
S: AsRef<str>,
R: Into<Robj>,
{
fn sym_pair(self) -> (Option<Robj>, Robj) {
let val = self.0.as_ref();
let nm = if val.is_empty() {
None
} else {
Some(r!(Symbol::from_string(val)))
};
(nm, self.1.into())
}
}
impl<S, R> SymPair for &(S, R)
where
S: AsRef<str>,
R: Into<Robj>,
R: Clone,
{
fn sym_pair(self) -> (Option<Robj>, Robj) {
let val = self.0.as_ref();
let nm = if val.is_empty() {
None
} else {
Some(r!(Symbol::from_string(val)))
};
(nm, self.1.clone().into())
}
}