use crate::{libR::{TYPEOF, Rf_protect, Rf_unprotect_ptr}, RType::{RType, RTypeMut}};
use core::{ops::{Index, IndexMut}, marker::PhantomData};
#[derive(Copy,Clone)]
#[repr(transparent)]
pub struct SEXP<T:RType>{
sexp:crate::libR::SEXP,
_marker:[PhantomData<T>;0]
}
#[repr(transparent)]
pub struct Owned<T:RType>{
sexp:crate::libR::SEXP,
_marker:[PhantomData<T>;0]
}
impl<T:RType> Owned<T> {
pub fn protect(self)->Protected<T> {
self.into()
}
}
#[repr(transparent)]
pub struct Protected<T:RType>{
sexp:crate::libR::SEXP,
_marker:[PhantomData<T>;0]
}
pub trait SExt:Sized {
type Data:RType;
fn as_sexp(&self) -> crate::libR::SEXP;
fn new(len: <Self::Data as RType>::New ) -> Self where Self:Newable;
#[inline(always)]
fn is_correct_type(&self) -> bool {
Self::Data::is_type(self.as_sexp())
}
#[inline(always)]
fn len(&self) -> usize {
crate::RType::len(self.as_sexp()) as usize
}
#[inline(always)]
unsafe fn data_unchecked(&self) -> &[<Self::Data as RType>::Data] {
unsafe { core::slice::from_raw_parts(Self::Data::data(self.as_sexp()), self.len()) }
}
#[inline(always)]
fn data(&self) -> &[<Self::Data as RType>::Data] {
if self.len()==0 {
&[]
} else {
if self.is_correct_type() {
unsafe {self.data_unchecked()}
} else {
panic!(
"data has the type {}, but {}(={}) is required.",
unsafe{TYPEOF(self.as_sexp())},
core::any::type_name::<<Self::Data as RType>::Data>(),
<Self::Data as RType>::SEXPTYPE,
)
}
}
}
#[inline(always)]
unsafe fn data_unchecked_mut(&self) -> &mut [<Self::Data as RType>::Data] where <Self as SExt>::Data: RTypeMut, Self:Mutable {
unsafe { core::slice::from_raw_parts_mut(Self::Data::data_mut(self.as_sexp()), self.len()) }
}
#[inline(always)]
fn data_mut(&mut self) -> &mut [<Self::Data as RType>::Data] where <Self as SExt>::Data: RTypeMut, Self:Mutable {
if self.len()==0 {
&mut []
} else {
if self.is_correct_type() {
unsafe {self.data_unchecked_mut()}
} else {
panic!(
"data has the type {}, but {}(={}) is required.",
unsafe{TYPEOF(self.as_sexp())},
core::any::type_name::<Self::Data>(),
<Self::Data as RType>::SEXPTYPE,
)
}
}
}
}
pub trait Newable {}
impl<T:RType> Newable for Owned<T>{}
pub trait Mutable {}
impl<T:RTypeMut> Mutable for Owned<T>{}
impl<T:RTypeMut> Mutable for Protected<T>{}
impl<T:RType> SExt for SEXP<T> {
type Data=T;
fn as_sexp(&self) -> crate::libR::SEXP {
self.sexp
}
fn new(len:<Self::Data as RType>::New)->Self{
Self{sexp:Self::Data::new(len),_marker:[]}
}
}
impl<T:RType> SExt for Owned<T> {
type Data=T;
fn as_sexp(&self) -> crate::libR::SEXP {
self.sexp
}
fn new(len:<Self::Data as RType>::New)->Self{
Self{sexp:Self::Data::new(len),_marker:[]}
}
}
impl<T:RType> SExt for Protected<T> {
type Data=T;
fn as_sexp(&self) -> crate::libR::SEXP {
self.sexp
}
fn new(len:<Self::Data as RType>::New)->Self{
Self{sexp:unsafe { Rf_protect(Self::Data::new(len)) },_marker:[]}
}
}
impl<T:RType> From<Owned<T>> for Protected<T> {
#[inline(always)]
fn from(s: Owned<T>) -> Self {
Self{sexp:unsafe { Rf_protect(s.sexp) },_marker:[]}
}
}
impl<T:RType> From<Protected<T>> for Owned<T> {
#[inline(always)]
fn from(s: Protected<T>) -> Self {
Self{sexp:s.sexp ,_marker:[]}
}
}
impl<T:RType> From<Protected<T>> for SEXP<T> {
#[inline(always)]
fn from(s: Protected<T>) -> Self {
Self{sexp:s.sexp,_marker:[]}
}
}
impl<T:RType> From<Owned<T>> for SEXP<T> {
#[inline(always)]
fn from(s: Owned<T>) -> Self {
Self{sexp:s.sexp,_marker:[]}
}
}
impl<T:RType> Drop for Protected<T> {
#[inline(always)]
fn drop(&mut self) {
unsafe { Rf_unprotect_ptr(self.sexp) }
}
}
impl_index!{SEXP Owned Protected}