1use crate::SexpExt;
26use crate::from_r::{SexpError, SexpLengthError, SexpNaError, SexpTypeError, TryFromSexp};
27use crate::into_r::IntoR;
28use crate::sexp_types::{Rcomplex, SEXPTYPE};
29use crate::{IsNA, SEXP};
30
31#[derive(#[automatically_derived]
impl ::core::fmt::Debug for RValue {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Null => ::core::fmt::Formatter::write_str(f, "Null"),
Self::Logical(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Logical", &__self_0),
Self::Integer(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Integer", &__self_0),
Self::Double(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Double",
&__self_0),
Self::Complex(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Complex", &__self_0),
Self::Character(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Character", &__self_0),
Self::Raw(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Raw",
&__self_0),
Self::List(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "List",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for RValue {
#[inline]
fn clone(&self) -> Self {
match self {
Self::Null => RValue::Null,
Self::Logical(__self_0) =>
RValue::Logical(::core::clone::Clone::clone(__self_0)),
Self::Integer(__self_0) =>
RValue::Integer(::core::clone::Clone::clone(__self_0)),
Self::Double(__self_0) =>
RValue::Double(::core::clone::Clone::clone(__self_0)),
Self::Complex(__self_0) =>
RValue::Complex(::core::clone::Clone::clone(__self_0)),
Self::Character(__self_0) =>
RValue::Character(::core::clone::Clone::clone(__self_0)),
Self::Raw(__self_0) =>
RValue::Raw(::core::clone::Clone::clone(__self_0)),
Self::List(__self_0) =>
RValue::List(::core::clone::Clone::clone(__self_0)),
}
}
}Clone)]
33pub enum RValue {
34 Null,
36 Logical(Vec<Option<bool>>),
38 Integer(Vec<Option<i32>>),
40 Double(Vec<f64>),
42 Complex(Vec<Rcomplex>),
44 Character(Vec<Option<String>>),
46 Raw(Vec<u8>),
48 List(Vec<(Option<String>, RValue)>),
50}
51
52impl IntoR for RValue {
55 type Error = std::convert::Infallible;
56
57 fn try_into_sexp(self) -> Result<SEXP, Self::Error> {
58 Ok(self.into_sexp())
59 }
60
61 unsafe fn try_into_sexp_unchecked(self) -> Result<SEXP, Self::Error> {
62 self.try_into_sexp()
63 }
64
65 fn into_sexp(self) -> SEXP {
66 match self {
67 RValue::Null => SEXP::nil(),
68 RValue::Logical(v) => v.into_sexp(),
69 RValue::Integer(v) => v.into_sexp(),
70 RValue::Double(v) => v.into_sexp(),
71 RValue::Complex(v) => v.into_sexp(),
72 RValue::Character(v) => v.into_sexp(),
73 RValue::Raw(v) => v.into_sexp(),
74 RValue::List(pairs) => list_into_sexp(pairs),
75 }
76 }
77}
78
79fn list_into_sexp(pairs: Vec<(Option<String>, RValue)>) -> SEXP {
85 use crate::list::List;
86 unsafe {
89 let scope = crate::gc_protect::ProtectScope::new();
90 if pairs.iter().any(|(name, _)| name.is_some()) {
91 let named: Vec<(String, SEXP)> = pairs
93 .into_iter()
94 .map(|(name, val)| (name.unwrap_or_default(), scope.protect_raw(val.into_sexp())))
95 .collect();
96 List::from_raw_pairs(named).into_sexp()
97 } else {
98 let values: Vec<SEXP> = pairs
99 .into_iter()
100 .map(|(_, val)| scope.protect_raw(val.into_sexp()))
101 .collect();
102 List::from_raw_values(values).into_sexp()
103 }
104 }
105}
106
107impl TryFromSexp for RValue {
112 type Error = SexpError;
113
114 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
115 let n = sexp.len();
116 match sexp.type_of() {
117 SEXPTYPE::NILSXP => Ok(RValue::Null),
118 SEXPTYPE::LGLSXP => Ok(RValue::Logical(
119 (0..n as isize)
120 .map(|i| {
121 let x = sexp.logical_elt(i);
122 (!x.is_na()).then_some(x != 0)
123 })
124 .collect(),
125 )),
126 SEXPTYPE::INTSXP => Ok(RValue::Integer(
127 (0..n as isize)
128 .map(|i| {
129 let x = sexp.integer_elt(i);
130 (!x.is_na()).then_some(x)
131 })
132 .collect(),
133 )),
134 SEXPTYPE::REALSXP => Ok(RValue::Double(
136 (0..n as isize).map(|i| sexp.real_elt(i)).collect(),
137 )),
138 SEXPTYPE::CPLXSXP => Ok(RValue::Complex(
139 (0..n as isize).map(|i| sexp.complex_elt(i)).collect(),
140 )),
141 SEXPTYPE::STRSXP => Ok(RValue::Character(
142 (0..n as isize)
143 .map(|i| {
144 if sexp.string_elt(i).is_na_string() {
145 None
146 } else {
147 sexp.string_elt_str(i).map(str::to_string)
148 }
149 })
150 .collect(),
151 )),
152 SEXPTYPE::RAWSXP => Ok(RValue::Raw(unsafe { sexp.as_slice::<u8>() }.to_vec())),
154 SEXPTYPE::VECSXP => {
155 let names = sexp.get_names();
156 let mut pairs = Vec::with_capacity(n);
157 for i in 0..n as isize {
158 let name = if names.is_nil()
161 || !names.is_character()
162 || names.string_elt(i).is_na_string()
163 {
164 None
165 } else {
166 names
167 .string_elt_str(i)
168 .filter(|s| !s.is_empty())
169 .map(str::to_string)
170 };
171 pairs.push((name, RValue::try_from_sexp(sexp.vector_elt(i))?));
172 }
173 Ok(RValue::List(pairs))
174 }
175 other => Err(SexpError::InvalidValue(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("RValue cannot represent SEXP of type {0:?} (only R data vectors are modelled)",
other))
})format!(
176 "RValue cannot represent SEXP of type {other:?} (only R data vectors are modelled)"
177 ))),
178 }
179 }
180}
181
182impl From<i32> for RValue {
187 fn from(v: i32) -> Self {
188 RValue::Integer(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(v)]))vec![Some(v)])
189 }
190}
191impl From<f64> for RValue {
192 fn from(v: f64) -> Self {
193 RValue::Double(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[v]))vec![v])
194 }
195}
196impl From<bool> for RValue {
197 fn from(v: bool) -> Self {
198 RValue::Logical(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(v)]))vec![Some(v)])
199 }
200}
201impl From<String> for RValue {
202 fn from(v: String) -> Self {
203 RValue::Character(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(v)]))vec![Some(v)])
204 }
205}
206impl From<&str> for RValue {
207 fn from(v: &str) -> Self {
208 RValue::Character(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(v.to_string())]))vec![Some(v.to_string())])
209 }
210}
211impl From<Vec<i32>> for RValue {
212 fn from(v: Vec<i32>) -> Self {
213 RValue::Integer(v.into_iter().map(Some).collect())
214 }
215}
216impl From<Vec<f64>> for RValue {
217 fn from(v: Vec<f64>) -> Self {
218 RValue::Double(v)
219 }
220}
221impl From<Vec<bool>> for RValue {
222 fn from(v: Vec<bool>) -> Self {
223 RValue::Logical(v.into_iter().map(Some).collect())
224 }
225}
226impl From<Vec<String>> for RValue {
227 fn from(v: Vec<String>) -> Self {
228 RValue::Character(v.into_iter().map(Some).collect())
229 }
230}
231impl From<Vec<&str>> for RValue {
232 fn from(v: Vec<&str>) -> Self {
233 RValue::Character(v.into_iter().map(|s| Some(s.to_string())).collect())
234 }
235}
236
237macro_rules! impl_tuple_rvalue {
242 ($n:literal, $name:literal; $($T:ident $R:ident $idx:tt),+) => {
243 impl<$($T: Into<RValue>),+> From<($($T,)+)> for RValue {
244 fn from(value: ($($T,)+)) -> Self {
245 Self::List(vec![$((None, value.$idx.into()),)+])
246 }
247 }
248 };
249}
250
251impl<A: Into<RValue>, B: Into<RValue>, C: Into<RValue>, D: Into<RValue>,
E: Into<RValue>, F: Into<RValue>, G: Into<RValue>, H: Into<RValue>,
I: Into<RValue>, J: Into<RValue>, K: Into<RValue>, L: Into<RValue>>
From<(A, B, C, D, E, F, G, H, I, J, K, L)> for RValue {
fn from(value: (A, B, C, D, E, F, G, H, I, J, K, L)) -> Self {
Self::List(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(None, value.0.into()), (None, value.1.into()),
(None, value.2.into()), (None, value.3.into()),
(None, value.4.into()), (None, value.5.into()),
(None, value.6.into()), (None, value.7.into()),
(None, value.8.into()), (None, value.9.into()),
(None, value.10.into()), (None, value.11.into())])))
}
}crate::tuple_macros::for_each_tuple!(impl_tuple_rvalue);
252
253impl From<Option<i32>> for RValue {
262 fn from(v: Option<i32>) -> Self {
263 RValue::Integer(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[v]))vec![v])
264 }
265}
266impl From<Option<f64>> for RValue {
267 fn from(v: Option<f64>) -> Self {
268 RValue::Double(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[v.unwrap_or(crate::altrep_traits::NA_REAL)]))vec![v.unwrap_or(crate::altrep_traits::NA_REAL)])
269 }
270}
271impl From<Option<bool>> for RValue {
272 fn from(v: Option<bool>) -> Self {
273 RValue::Logical(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[v]))vec![v])
274 }
275}
276impl From<Option<String>> for RValue {
277 fn from(v: Option<String>) -> Self {
278 RValue::Character(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[v]))vec![v])
279 }
280}
281impl From<Option<&str>> for RValue {
282 fn from(v: Option<&str>) -> Self {
283 RValue::Character(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[v.map(str::to_string)]))vec![v.map(str::to_string)])
284 }
285}
286impl From<Vec<Option<i32>>> for RValue {
287 fn from(v: Vec<Option<i32>>) -> Self {
288 RValue::Integer(v)
289 }
290}
291impl From<Vec<Option<f64>>> for RValue {
292 fn from(v: Vec<Option<f64>>) -> Self {
293 RValue::Double(
294 v.into_iter()
295 .map(|x| x.unwrap_or(crate::altrep_traits::NA_REAL))
296 .collect(),
297 )
298 }
299}
300impl From<Vec<Option<bool>>> for RValue {
301 fn from(v: Vec<Option<bool>>) -> Self {
302 RValue::Logical(v)
303 }
304}
305impl From<Vec<Option<String>>> for RValue {
306 fn from(v: Vec<Option<String>>) -> Self {
307 RValue::Character(v)
308 }
309}
310impl From<Vec<Option<&str>>> for RValue {
311 fn from(v: Vec<Option<&str>>) -> Self {
312 RValue::Character(v.into_iter().map(|s| s.map(str::to_string)).collect())
313 }
314}
315
316impl From<i64> for RValue {
320 fn from(v: i64) -> Self {
321 match i32::try_from(v) {
322 Ok(n) if !n.is_na() => RValue::Integer(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(n)]))vec![Some(n)]),
323 _ => RValue::Double(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[v as f64]))vec![v as f64]),
326 }
327 }
328}
329impl From<u32> for RValue {
330 fn from(v: u32) -> Self {
333 RValue::from(i64::from(v))
334 }
335}
336
337impl RValue {
342 pub fn sexptype(&self) -> SEXPTYPE {
344 match self {
345 RValue::Null => SEXPTYPE::NILSXP,
346 RValue::Logical(_) => SEXPTYPE::LGLSXP,
347 RValue::Integer(_) => SEXPTYPE::INTSXP,
348 RValue::Double(_) => SEXPTYPE::REALSXP,
349 RValue::Complex(_) => SEXPTYPE::CPLXSXP,
350 RValue::Character(_) => SEXPTYPE::STRSXP,
351 RValue::Raw(_) => SEXPTYPE::RAWSXP,
352 RValue::List(_) => SEXPTYPE::VECSXP,
353 }
354 }
355
356 pub fn is_null(&self) -> bool {
358 #[allow(non_exhaustive_omitted_patterns)] match self {
RValue::Null => true,
_ => false,
}matches!(self, RValue::Null)
359 }
360
361 pub fn debug<T: std::fmt::Debug>(value: T) -> Self {
371 RValue::Character(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", value))
}))]))vec![Some(format!("{value:?}"))])
372 }
373
374 pub fn as_i32(&self) -> Option<i32> {
380 match self {
381 RValue::Integer(v) if v.len() == 1 => v[0],
382 _ => None,
383 }
384 }
385
386 pub fn as_f64(&self) -> Option<f64> {
392 match self {
393 RValue::Double(v) if v.len() == 1 => {
394 let x = v[0];
395 (!x.is_na()).then_some(x)
396 }
397 _ => None,
398 }
399 }
400
401 pub fn as_bool(&self) -> Option<bool> {
403 match self {
404 RValue::Logical(v) if v.len() == 1 => v[0],
405 _ => None,
406 }
407 }
408
409 pub fn as_str(&self) -> Option<&str> {
411 match self {
412 RValue::Character(v) if v.len() == 1 => v[0].as_deref(),
413 _ => None,
414 }
415 }
416}
417
418fn wrong_type(expected: SEXPTYPE, actual: &RValue) -> SexpError {
420 SexpError::Type(SexpTypeError {
421 expected,
422 actual: actual.sexptype(),
423 })
424}
425
426macro_rules! try_from_scalar_opt {
432 ($t:ty, $variant:ident, $ty:expr) => {
433 impl TryFrom<RValue> for $t {
434 type Error = SexpError;
435 fn try_from(value: RValue) -> Result<Self, SexpError> {
436 match value {
437 RValue::$variant(xs) => {
438 if xs.len() != 1 {
439 return Err(SexpError::Length(SexpLengthError {
440 expected: 1,
441 actual: xs.len(),
442 }));
443 }
444 xs.into_iter()
445 .next()
446 .unwrap()
447 .ok_or(SexpError::Na(SexpNaError { sexp_type: $ty }))
448 }
449 other => Err(wrong_type($ty, &other)),
450 }
451 }
452 }
453 };
454}
455impl TryFrom<RValue> for i32 {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Integer(xs) => {
if xs.len() != 1 {
return Err(SexpError::Length(SexpLengthError {
expected: 1,
actual: xs.len(),
}));
}
xs.into_iter().next().unwrap().ok_or(SexpError::Na(SexpNaError {
sexp_type: SEXPTYPE::INTSXP,
}))
}
other => Err(wrong_type(SEXPTYPE::INTSXP, &other)),
}
}
}try_from_scalar_opt!(i32, Integer, SEXPTYPE::INTSXP);
456impl TryFrom<RValue> for bool {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Logical(xs) => {
if xs.len() != 1 {
return Err(SexpError::Length(SexpLengthError {
expected: 1,
actual: xs.len(),
}));
}
xs.into_iter().next().unwrap().ok_or(SexpError::Na(SexpNaError {
sexp_type: SEXPTYPE::LGLSXP,
}))
}
other => Err(wrong_type(SEXPTYPE::LGLSXP, &other)),
}
}
}try_from_scalar_opt!(bool, Logical, SEXPTYPE::LGLSXP);
457impl TryFrom<RValue> for String {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Character(xs) => {
if xs.len() != 1 {
return Err(SexpError::Length(SexpLengthError {
expected: 1,
actual: xs.len(),
}));
}
xs.into_iter().next().unwrap().ok_or(SexpError::Na(SexpNaError {
sexp_type: SEXPTYPE::STRSXP,
}))
}
other => Err(wrong_type(SEXPTYPE::STRSXP, &other)),
}
}
}try_from_scalar_opt!(String, Character, SEXPTYPE::STRSXP);
458
459impl TryFrom<RValue> for f64 {
461 type Error = SexpError;
462 fn try_from(value: RValue) -> Result<Self, SexpError> {
463 match value {
464 RValue::Double(xs) => {
465 if xs.len() != 1 {
466 return Err(SexpError::Length(SexpLengthError {
467 expected: 1,
468 actual: xs.len(),
469 }));
470 }
471 let x = xs[0];
472 if x.is_na() {
474 Err(SexpError::Na(SexpNaError {
475 sexp_type: SEXPTYPE::REALSXP,
476 }))
477 } else {
478 Ok(x)
479 }
480 }
481 other => Err(wrong_type(SEXPTYPE::REALSXP, &other)),
482 }
483 }
484}
485
486macro_rules! try_from_vec {
488 ($t:ty, $variant:ident, $ty:expr) => {
489 impl TryFrom<RValue> for $t {
490 type Error = SexpError;
491 fn try_from(value: RValue) -> Result<Self, SexpError> {
492 match value {
493 RValue::$variant(xs) => Ok(xs),
494 other => Err(wrong_type($ty, &other)),
495 }
496 }
497 }
498 };
499}
500impl TryFrom<RValue> for Vec<Option<bool>> {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Logical(xs) => Ok(xs),
other => Err(wrong_type(SEXPTYPE::LGLSXP, &other)),
}
}
}try_from_vec!(Vec<Option<bool>>, Logical, SEXPTYPE::LGLSXP);
501impl TryFrom<RValue> for Vec<Option<i32>> {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Integer(xs) => Ok(xs),
other => Err(wrong_type(SEXPTYPE::INTSXP, &other)),
}
}
}try_from_vec!(Vec<Option<i32>>, Integer, SEXPTYPE::INTSXP);
502impl TryFrom<RValue> for Vec<f64> {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Double(xs) => Ok(xs),
other => Err(wrong_type(SEXPTYPE::REALSXP, &other)),
}
}
}try_from_vec!(Vec<f64>, Double, SEXPTYPE::REALSXP);
503impl TryFrom<RValue> for Vec<Rcomplex> {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Complex(xs) => Ok(xs),
other => Err(wrong_type(SEXPTYPE::CPLXSXP, &other)),
}
}
}try_from_vec!(Vec<Rcomplex>, Complex, SEXPTYPE::CPLXSXP);
504impl TryFrom<RValue> for Vec<Option<String>> {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Character(xs) => Ok(xs),
other => Err(wrong_type(SEXPTYPE::STRSXP, &other)),
}
}
}try_from_vec!(Vec<Option<String>>, Character, SEXPTYPE::STRSXP);
505impl TryFrom<RValue> for Vec<u8> {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::Raw(xs) => Ok(xs),
other => Err(wrong_type(SEXPTYPE::RAWSXP, &other)),
}
}
}try_from_vec!(Vec<u8>, Raw, SEXPTYPE::RAWSXP);
506impl TryFrom<RValue> for Vec<(Option<String>, RValue)> {
type Error = SexpError;
fn try_from(value: RValue) -> Result<Self, SexpError> {
match value {
RValue::List(xs) => Ok(xs),
other => Err(wrong_type(SEXPTYPE::VECSXP, &other)),
}
}
}try_from_vec!(Vec<(Option<String>, RValue)>, List, SEXPTYPE::VECSXP);
507
508#[cfg(test)]
511mod tests {
512 use super::*;
513
514 #[test]
517 fn as_scalar_accessors() {
518 assert_eq!(RValue::from(7i32).as_i32(), Some(7));
519 assert_eq!(RValue::from(1.5).as_f64(), Some(1.5));
520 assert_eq!(RValue::from(true).as_bool(), Some(true));
521 assert_eq!(RValue::from("hi").as_str(), Some("hi"));
522
523 assert_eq!(RValue::from("hi").as_i32(), None);
525 assert_eq!(RValue::Integer(vec![Some(1), Some(2)]).as_i32(), None);
527 assert_eq!(RValue::Integer(vec![None]).as_i32(), None);
529 assert_eq!(
530 RValue::Double(vec![crate::altrep_traits::NA_REAL]).as_f64(),
531 None
532 );
533 assert!(RValue::Null.is_null());
534 }
535
536 #[test]
537 fn try_from_scalar_ok_and_errors() {
538 assert_eq!(i32::try_from(RValue::from(7i32)).unwrap(), 7);
539 assert_eq!(f64::try_from(RValue::from(2.5)).unwrap(), 2.5);
540 assert!(!bool::try_from(RValue::from(false)).unwrap());
541 assert_eq!(String::try_from(RValue::from("x")).unwrap(), "x");
542
543 assert!(matches!(
545 i32::try_from(RValue::from("x")),
546 Err(SexpError::Type(_))
547 ));
548 assert!(matches!(
550 i32::try_from(RValue::Integer(vec![Some(1), Some(2)])),
551 Err(SexpError::Length(_))
552 ));
553 assert!(matches!(
555 i32::try_from(RValue::Integer(vec![None])),
556 Err(SexpError::Na(_))
557 ));
558 assert!(matches!(
559 f64::try_from(RValue::Double(vec![crate::altrep_traits::NA_REAL])),
560 Err(SexpError::Na(_))
561 ));
562 }
563
564 #[test]
567 fn double_na_follows_r_is_na() {
568 let computed = f64::from_bits(0x7FF8_0000_0000_07A2);
569 assert_eq!(RValue::Double(vec![computed]).as_f64(), None);
570 assert!(matches!(
571 f64::try_from(RValue::Double(vec![computed])),
572 Err(SexpError::Na(_))
573 ));
574 assert!(
575 RValue::Double(vec![f64::NAN])
576 .as_f64()
577 .is_some_and(f64::is_nan)
578 );
579 assert!(f64::try_from(RValue::Double(vec![f64::NAN])).is_ok_and(f64::is_nan));
580 }
581
582 #[test]
583 fn from_option_scalars() {
584 assert!(matches!(RValue::from(Some(7_i32)), RValue::Integer(v) if v == vec![Some(7)]));
585 assert!(matches!(RValue::from(None::<i32>), RValue::Integer(v) if v == vec![None]));
586 assert!(matches!(RValue::from(Some(true)), RValue::Logical(v) if v == vec![Some(true)]));
587 assert!(matches!(RValue::from(None::<bool>), RValue::Logical(v) if v == vec![None]));
588 assert!(
589 matches!(RValue::from(Some("x")), RValue::Character(v) if v == vec![Some("x".to_string())])
590 );
591 assert!(matches!(RValue::from(None::<&str>), RValue::Character(v) if v == vec![None]));
592 assert!(
593 matches!(RValue::from(Some("y".to_string())), RValue::Character(v) if v == vec![Some("y".to_string())])
594 );
595
596 assert_eq!(RValue::from(Some(1.5_f64)).as_f64(), Some(1.5));
598 assert_eq!(RValue::from(None::<f64>).as_f64(), None);
599 }
600
601 #[test]
602 fn from_vec_option() {
603 assert!(
604 matches!(RValue::from(vec![Some(1_i32), None, Some(3)]), RValue::Integer(v) if v == vec![Some(1), None, Some(3)])
605 );
606 assert!(
607 matches!(RValue::from(vec![Some(true), None]), RValue::Logical(v) if v == vec![Some(true), None])
608 );
609 assert!(
610 matches!(RValue::from(vec![Some("a".to_string()), None]), RValue::Character(v) if v == vec![Some("a".to_string()), None])
611 );
612 assert!(
613 matches!(RValue::from(vec![Some("b"), None]), RValue::Character(v) if v == vec![Some("b".to_string()), None])
614 );
615
616 let RValue::Double(v) = RValue::from(vec![Some(0.5_f64), None]) else {
618 panic!("expected Double");
619 };
620 assert_eq!(v[0], 0.5);
621 assert_eq!(v[1].to_bits(), crate::altrep_traits::NA_REAL.to_bits());
622 }
623
624 #[test]
625 fn from_wide_integer_ladder() {
626 assert!(matches!(RValue::from(42_i64), RValue::Integer(v) if v == vec![Some(42)]));
628 assert!(
629 matches!(RValue::from(i32::MAX as i64), RValue::Integer(v) if v == vec![Some(i32::MAX)])
630 );
631 assert!(matches!(RValue::from(7_u32), RValue::Integer(v) if v == vec![Some(7)]));
632 assert!(matches!(RValue::from(i32::MIN as i64), RValue::Double(_)));
634 assert!(
636 matches!(RValue::from(i32::MAX as i64 + 1), RValue::Double(v) if v == vec![(i32::MAX as i64 + 1) as f64])
637 );
638 assert!(
640 matches!(RValue::from(u32::MAX), RValue::Double(v) if v == vec![f64::from(u32::MAX)])
641 );
642 }
643
644 #[test]
645 fn debug_stringifies() {
646 assert_eq!(RValue::debug(0..=100).as_str(), Some("0..=100"));
647 assert_eq!(RValue::debug(vec![1, 2]).as_str(), Some("[1, 2]"));
648 }
649
650 #[test]
651 fn try_from_whole_vector() {
652 let v: Vec<Option<i32>> = RValue::Integer(vec![Some(1), None]).try_into().unwrap();
653 assert_eq!(v, vec![Some(1), None]);
654
655 let raw: Vec<u8> = RValue::Raw(vec![1, 2, 3]).try_into().unwrap();
656 assert_eq!(raw, vec![1, 2, 3]);
657
658 let bad: Result<Vec<u8>, _> = RValue::from(1i32).try_into();
660 assert!(matches!(bad, Err(SexpError::Type(_))));
661 }
662}