use super::*;
macro_rules! impl_try_from_scalar_integer {
($t:ty) => {
impl TryFrom<&Robj> for $t {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
match robj.len() {
0 => return Err(Error::ExpectedNonZeroLength(robj.clone())),
1 => {}
_ => return Err(Error::ExpectedScalar(robj.clone())),
};
if robj.is_na() {
return Err(Error::MustNotBeNA(robj.clone()));
}
if let Some(v) = robj.as_integer() {
if let Ok(v) = Self::try_from(v) {
return Ok(v);
} else {
return Err(Error::OutOfLimits(robj.clone()));
}
}
if let Some(v) = robj.as_real() {
let result = v as Self;
if (result as f64 - v).abs() < f64::EPSILON {
return Ok(result);
} else {
return Err(Error::ExpectedWholeNumber(robj.clone()));
}
}
Err(Error::ExpectedNumeric(robj.clone()))
}
}
};
}
macro_rules! impl_try_from_scalar_real {
($t:ty) => {
impl TryFrom<&Robj> for $t {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
match robj.len() {
0 => return Err(Error::ExpectedNonZeroLength(robj.clone())),
1 => {}
_ => return Err(Error::ExpectedScalar(robj.clone())),
};
if robj.is_na() {
return Err(Error::MustNotBeNA(robj.clone()));
}
if let Some(v) = robj.as_real() {
return Ok(v as Self);
}
if let Some(v) = robj.as_integer() {
return Ok(v as Self);
}
Err(Error::ExpectedNumeric(robj.clone()))
}
}
};
}
impl_try_from_scalar_integer!(u8);
impl_try_from_scalar_integer!(u16);
impl_try_from_scalar_integer!(u32);
impl_try_from_scalar_integer!(u64);
impl_try_from_scalar_integer!(usize);
impl_try_from_scalar_integer!(i8);
impl_try_from_scalar_integer!(i16);
impl_try_from_scalar_integer!(i32);
impl_try_from_scalar_integer!(i64);
impl_try_from_scalar_integer!(isize);
impl_try_from_scalar_real!(f32);
impl_try_from_scalar_real!(f64);
impl TryFrom<&Robj> for bool {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if robj.is_na() {
Err(Error::MustNotBeNA(robj.clone()))
} else {
Ok(<Rbool>::try_from(robj)?.is_true())
}
}
}
impl TryFrom<&Robj> for &str {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if robj.is_na() {
return Err(Error::MustNotBeNA(robj.clone()));
}
match robj.len() {
0 => Err(Error::ExpectedNonZeroLength(robj.clone())),
1 => {
if let Some(s) = robj.as_str() {
Ok(s)
} else {
Err(Error::ExpectedString(robj.clone()))
}
}
_ => Err(Error::ExpectedScalar(robj.clone())),
}
}
}
impl TryFrom<&Robj> for String {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
<&str>::try_from(robj).map(|s| s.to_string())
}
}
impl TryFrom<&Robj> for Vec<i32> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(v) = robj.as_typed_slice() {
Ok(Vec::from(v))
} else {
Err(Error::ExpectedInteger(robj.clone()))
}
}
}
impl TryFrom<&Robj> for Vec<f64> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(v) = robj.as_typed_slice() {
Ok(Vec::from(v))
} else {
Err(Error::ExpectedReal(robj.clone()))
}
}
}
impl TryFrom<&Robj> for Vec<u8> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(v) = robj.as_typed_slice() {
Ok(Vec::from(v))
} else {
Err(Error::ExpectedRaw(robj.clone()))
}
}
}
impl TryFrom<&Robj> for Vec<Rint> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(v) = robj.as_typed_slice() {
Ok(Vec::from(v))
} else {
Err(Error::ExpectedInteger(robj.clone()))
}
}
}
impl TryFrom<&Robj> for Vec<Rfloat> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(v) = robj.as_typed_slice() {
Ok(Vec::from(v))
} else {
Err(Error::ExpectedReal(robj.clone()))
}
}
}
impl TryFrom<&Robj> for Vec<Rbool> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(v) = robj.as_typed_slice() {
Ok(Vec::from(v))
} else {
Err(Error::ExpectedInteger(robj.clone()))
}
}
}
impl TryFrom<&Robj> for Vec<Rcplx> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(v) = robj.as_typed_slice() {
Ok(Vec::from(v))
} else {
Err(Error::ExpectedComplex(robj.clone()))
}
}
}
impl TryFrom<&Robj> for Vec<String> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if let Some(iter) = robj.as_str_iter() {
if iter.clone().any(|s| s.is_na()) {
Err(Error::MustNotBeNA(robj.clone()))
} else {
Ok(iter.map(|s| s.to_string()).collect::<Vec<String>>())
}
} else {
Err(Error::ExpectedString(robj.clone()))
}
}
}
impl TryFrom<&Robj> for &[i32] {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
robj.as_typed_slice()
.ok_or_else(|| Error::ExpectedInteger(robj.clone()))
}
}
impl TryFrom<&Robj> for &[Rint] {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
robj.as_typed_slice()
.ok_or_else(|| Error::ExpectedInteger(robj.clone()))
}
}
impl TryFrom<&Robj> for &[Rfloat] {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
robj.as_typed_slice()
.ok_or_else(|| Error::ExpectedReal(robj.clone()))
}
}
impl TryFrom<&Robj> for &[Rbool] {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
robj.as_typed_slice()
.ok_or_else(|| Error::ExpectedLogical(robj.clone()))
}
}
impl TryFrom<&Robj> for &[Rcplx] {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
robj.as_typed_slice()
.ok_or_else(|| Error::ExpectedComplex(robj.clone()))
}
}
impl TryFrom<&Robj> for &[u8] {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
robj.as_typed_slice()
.ok_or_else(|| Error::ExpectedRaw(robj.clone()))
}
}
impl TryFrom<&Robj> for &[f64] {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
robj.as_typed_slice()
.ok_or_else(|| Error::ExpectedReal(robj.clone()))
}
}
impl TryFrom<&Robj> for Rcplx {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
match robj.len() {
0 => return Err(Error::ExpectedNonZeroLength(robj.clone())),
1 => {}
_ => return Err(Error::ExpectedScalar(robj.clone())),
};
if robj.is_na() {
return Ok(Rcplx::na());
}
if let Some(v) = robj.as_real() {
return Ok(Rcplx::from(v));
}
if let Some(v) = robj.as_integer() {
return Ok(Rcplx::from(v as f64));
}
if let Some(s) = robj.as_typed_slice() {
return Ok(s[0]);
}
Err(Error::ExpectedComplex(robj.clone()))
}
}
macro_rules! impl_try_from_robj {
($($type : ty)*) => {
$(
impl TryFrom<Robj> for $type {
type Error = Error;
fn try_from(robj: Robj) -> Result<Self> {
<$type>::try_from(&robj)
}
}
impl TryFrom<&Robj> for Option<$type> {
type Error = Error;
fn try_from(robj: &Robj) -> Result<Self> {
if robj.is_null() || robj.is_na() {
Ok(None)
} else {
Ok(Some(<$type>::try_from(robj)?))
}
}
}
impl TryFrom<Robj> for Option<$type> {
type Error = Error;
fn try_from(robj: Robj) -> Result<Self> {
<Option::<$type>>::try_from(&robj)
}
}
)*
}
}
impl_try_from_robj!(
u8 u16 u32 u64 usize
i8 i16 i32 i64 isize
bool
Rint Rfloat Rbool Rcplx
f32 f64
Vec::<Rint> Vec::<Rfloat> Vec::<Rbool> Vec::<Rcplx> Vec::<u8> Vec::<i32> Vec::<f64>
&[Rint] &[Rfloat] &[Rbool] &[Rcplx] &[u8] &[i32] &[f64]
&str String
);