Skip to content

Commit

Permalink
Add more documents [skip ci]
Browse files Browse the repository at this point in the history
  • Loading branch information
yutannihilation committed Jan 16, 2024
1 parent c8f77fb commit 667a3b4
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 13 deletions.
11 changes: 3 additions & 8 deletions src/sexp/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@ use savvy_ffi::{INTEGER, INTSXP, SEXP};
use super::{impl_common_sexp_ops, impl_common_sexp_ops_owned, Sexp};
use crate::protect;

// This is based on the idea of cpp11's `writable`.
//
// `IntegerSexp` is a read-only wrapper for SEXPs provided from outside of Rust;
// since it's the caller's responsibility to PROTECT it, we don't protect it on
// Rust's side.
//
// `OwnedIntegerSexp` is a writable wrapper for SEXPs newly allocated on Rust's
// side. Since it's us who produce it, we protect it and drop it.
/// An external SEXP of an integer vector.
pub struct IntegerSexp(pub SEXP);

/// A newly-created SEXP of an integer vector
pub struct OwnedIntegerSexp {
inner: SEXP,
token: SEXP,
Expand Down
3 changes: 3 additions & 0 deletions src/sexp/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use crate::{protect, OwnedStringSexp};

use super::{Sexp, TypedSexp};

/// An external SEXP of a list.
pub struct ListSexp(pub SEXP);

/// A newly-created SEXP of a list.
pub struct OwnedListSexp {
values: ListSexp,
names: Option<OwnedStringSexp>,
Expand Down
3 changes: 3 additions & 0 deletions src/sexp/logical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use savvy_ffi::{LGLSXP, LOGICAL, SET_LOGICAL_ELT, SEXP};
use super::{impl_common_sexp_ops, impl_common_sexp_ops_owned, Sexp};
use crate::protect;

/// An external SEXP of a logical vector.
pub struct LogicalSexp(pub SEXP);

/// A newly-created SEXP of a logical vector.
pub struct OwnedLogicalSexp {
inner: SEXP,
token: SEXP,
Expand Down
44 changes: 39 additions & 5 deletions src/sexp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,46 @@ pub mod real;
pub mod scalar;
pub mod string;

/// An `SEXP`.
pub struct Sexp(pub SEXP);

impl Sexp {
// There are two versions of Rf_isString(), but anyway this should be cheap.
//
// macro version: https://github.com/wch/r-source/blob/9065779ee510b7bd8ca93d08f4dd4b6e2bd31923/src/include/Defn.h#L759
// function version: https://github.com/wch/r-source/blob/9065779ee510b7bd8ca93d08f4dd4b6e2bd31923/src/main/memory.c#L4460
/// Returns `true` if the SEXP is a character vector.
pub fn is_string(&self) -> bool {
// There are two versions of `Rf_isString()``, but anyway this should be cheap.
//
// macro version: https://github.com/wch/r-source/blob/9065779ee510b7bd8ca93d08f4dd4b6e2bd31923/src/include/Defn.h#L759
// function version: https://github.com/wch/r-source/blob/9065779ee510b7bd8ca93d08f4dd4b6e2bd31923/src/main/memory.c#L4460
unsafe { Rf_isString(self.0) == 1 }
}

/// Returns `true` if the SEXP is an integer vector.
pub fn is_integer(&self) -> bool {
unsafe { Rf_isInteger(self.0) == 1 }
}

/// Returns `true` if the SEXP is a real vector.
pub fn is_real(&self) -> bool {
unsafe { Rf_isReal(self.0) == 1 }
}

/// Returns `true` if the SEXP is a logical vector.
pub fn is_logical(&self) -> bool {
unsafe { Rf_isLogical(self.0) == 1 }
}

// There's no test function for VECSXP. Rf_isList() is for pairlist
/// Returns `true` if the SEXP is a list.
pub fn is_list(&self) -> bool {
// There's no test function for VECSXP. Rf_isList() is for pairlist
unsafe { TYPEOF(self.0) as u32 == VECSXP }
}

/// Returns `true` if the SEXP is an external pointer.
pub fn is_external_pointer(&self) -> bool {
unsafe { TYPEOF(self.0) as u32 == EXTPTRSXP }
}

/// Returns the string representation of the SEXP type.
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn get_human_readable_type_name(&self) -> &'static str {
unsafe {
Expand All @@ -62,6 +70,7 @@ impl Sexp {
}
}

/// A typed version of `SEXP`.
pub enum TypedSexp {
Integer(IntegerSexp),
Real(RealSexp),
Expand Down Expand Up @@ -119,6 +128,7 @@ impl From<TypedSexp> for SEXP {
}

impl Sexp {
/// Downcast the `SEXP` to a concrete type.
pub fn into_typed(self) -> TypedSexp {
let ty = unsafe { TYPEOF(self.0) };
match ty as u32 {
Expand All @@ -132,6 +142,7 @@ impl Sexp {
}
}

/// Returns the specified attribute.
pub fn get_attrib(&self, attr: &str) -> crate::error::Result<Option<Sexp>> {
let attr_cstr = match CString::new(attr) {
Ok(cstr) => cstr,
Expand Down Expand Up @@ -162,14 +173,17 @@ impl Sexp {
}
}

/// Returns the S3 class.
pub fn get_class(&self) -> Option<Vec<&'static str>> {
unsafe { self.get_string_attrib_by_symbol(savvy_ffi::R_ClassSymbol) }
}

/// Returns the names.
pub fn get_names(&self) -> Option<Vec<&'static str>> {
unsafe { self.get_string_attrib_by_symbol(savvy_ffi::R_NamesSymbol) }
}

/// Set the input value to the specified attribute.
pub fn set_attrib(&mut self, attr: &str, value: Sexp) -> crate::error::Result<()> {
let attr_cstr = match CString::new(attr) {
Ok(cstr) => cstr,
Expand All @@ -195,10 +209,12 @@ impl Sexp {
Ok(())
}

/// Set the S3 class.
pub fn set_class(&mut self, classes: &[&str]) -> crate::error::Result<()> {
unsafe { self.set_string_attrib_by_symbol(savvy_ffi::R_ClassSymbol, classes) }
}

/// Set the names.
pub fn set_names(&mut self, names: &[&str]) -> crate::error::Result<()> {
unsafe { self.set_string_attrib_by_symbol(savvy_ffi::R_NamesSymbol, names) }
}
Expand Down Expand Up @@ -234,32 +250,39 @@ pub(crate) fn set_dim_to_sexp(value: SEXP, dim: &[usize]) -> crate::error::Resul
macro_rules! impl_common_sexp_ops {
($ty: ty) => {
impl $ty {
/// Returns the raw SEXP.
#[inline]
pub fn inner(&self) -> savvy_ffi::SEXP {
self.0
}

/// Returns the length of the SEXP.
pub fn len(&self) -> usize {
unsafe { savvy_ffi::Rf_xlength(self.inner()) as _ }
}

/// Returns `true` if the SEXP is of zero-length.
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}

/// Returns the specified attribute.
pub fn get_attrib(&self, attr: &str) -> crate::error::Result<Option<Sexp>> {
crate::Sexp(self.inner()).get_attrib(attr)
}

/// Returns the names.
pub fn get_names(&self) -> Option<Vec<&'static str>> {
crate::Sexp(self.inner()).get_names()
}

/// Returns the S3 class.
pub fn get_class(&self) -> Option<Vec<&'static str>> {
crate::Sexp(self.inner()).get_class()
}

/// Returns the dimension.
pub fn get_dim(&self) -> Option<Vec<usize>> {
crate::sexp::get_dim_from_sexp(self.inner())
}
Expand All @@ -270,49 +293,60 @@ macro_rules! impl_common_sexp_ops {
macro_rules! impl_common_sexp_ops_owned {
($ty: ty) => {
impl $ty {
/// Returns the raw SEXP.
#[inline]
pub fn inner(&self) -> SEXP {
self.inner
}

/// Returns the length of the SEXP.
#[inline]
pub fn len(&self) -> usize {
self.len
}

/// Returns `true` if the SEXP is of zero-length.
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}

/// Returns the specified attribute.
pub fn get_attrib(&self, attr: &str) -> crate::error::Result<Option<Sexp>> {
crate::Sexp(self.inner()).get_attrib(attr)
}

/// Returns the names.
pub fn get_names(&self) -> Option<Vec<&'static str>> {
crate::Sexp(self.inner()).get_names()
}

/// Returns the S3 class.
pub fn get_class(&self) -> Option<Vec<&'static str>> {
crate::Sexp(self.inner()).get_class()
}

/// Returns the dimension.
pub fn get_dim(&self) -> Option<Vec<usize>> {
crate::sexp::get_dim_from_sexp(self.inner())
}

/// Set the input value to the specified attribute.
pub fn set_attrib(&mut self, attr: &str, value: Sexp) -> crate::error::Result<()> {
crate::Sexp(self.inner()).set_attrib(attr, value)
}

/// Set the S3 class.
pub fn set_class(&mut self, classes: &[&str]) -> crate::error::Result<()> {
crate::Sexp(self.inner()).set_class(classes)
}

/// Set the names.
pub fn set_names(&mut self, names: &[&str]) -> crate::error::Result<()> {
crate::Sexp(self.inner()).set_names(names)
}

/// Set the dimension.
pub fn set_dim(&mut self, dim: &[usize]) -> crate::error::Result<()> {
crate::sexp::set_dim_to_sexp(self.inner(), dim)
}
Expand Down
3 changes: 3 additions & 0 deletions src/sexp/real.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use savvy_ffi::{REAL, REALSXP, SEXP};
use super::{impl_common_sexp_ops, impl_common_sexp_ops_owned, Sexp};
use crate::protect;

/// An external SEXP of a real vector.
pub struct RealSexp(pub SEXP);

/// A newly-created SEXP of a real vector.
pub struct OwnedRealSexp {
inner: SEXP,
token: SEXP,
Expand Down
3 changes: 3 additions & 0 deletions src/sexp/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use super::na::NotAvailableValue;
use super::{impl_common_sexp_ops, impl_common_sexp_ops_owned, Sexp};
use crate::protect;

/// An external SEXP of a character vector.
pub struct StringSexp(pub SEXP);

/// A newly-created SEXP of a character vector.
pub struct OwnedStringSexp {
inner: SEXP,
token: SEXP,
Expand Down

0 comments on commit 667a3b4

Please sign in to comment.