1use crate::SEXP;
22use crate::SexpExt;
23use crate::from_r::{SexpError, SexpLengthError, SexpNaError, SexpTypeError, TryFromSexp};
24use crate::into_r::IntoR;
25use crate::sexp_types::{Rcomplex, SEXPTYPE};
26
27#[derive(Debug, Clone)]
29pub enum RValue {
30 Null,
32 Logical(Vec<Option<bool>>),
34 Integer(Vec<Option<i32>>),
36 Double(Vec<f64>),
38 Complex(Vec<Rcomplex>),
40 Character(Vec<Option<String>>),
42 Raw(Vec<u8>),
44 List(Vec<(Option<String>, RValue)>),
46}
47
48impl IntoR for RValue {
51 type Error = std::convert::Infallible;
52
53 fn try_into_sexp(self) -> Result<SEXP, Self::Error> {
54 Ok(self.into_sexp())
55 }
56
57 unsafe fn try_into_sexp_unchecked(self) -> Result<SEXP, Self::Error> {
58 self.try_into_sexp()
59 }
60
61 fn into_sexp(self) -> SEXP {
62 match self {
63 RValue::Null => SEXP::nil(),
64 RValue::Logical(v) => v.into_sexp(),
65 RValue::Integer(v) => v.into_sexp(),
66 RValue::Double(v) => v.into_sexp(),
67 RValue::Complex(v) => v.into_sexp(),
68 RValue::Character(v) => v.into_sexp(),
69 RValue::Raw(v) => v.into_sexp(),
70 RValue::List(pairs) => list_into_sexp(pairs),
71 }
72 }
73}
74
75fn list_into_sexp(pairs: Vec<(Option<String>, RValue)>) -> SEXP {
81 use crate::list::List;
82 unsafe {
85 let scope = crate::gc_protect::ProtectScope::new();
86 if pairs.iter().any(|(name, _)| name.is_some()) {
87 let named: Vec<(String, SEXP)> = pairs
89 .into_iter()
90 .map(|(name, val)| (name.unwrap_or_default(), scope.protect_raw(val.into_sexp())))
91 .collect();
92 List::from_raw_pairs(named).into_sexp()
93 } else {
94 let values: Vec<SEXP> = pairs
95 .into_iter()
96 .map(|(_, val)| scope.protect_raw(val.into_sexp()))
97 .collect();
98 List::from_raw_values(values).into_sexp()
99 }
100 }
101}
102
103impl TryFromSexp for RValue {
108 type Error = SexpError;
109
110 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
111 use crate::altrep_traits::{NA_INTEGER, NA_LOGICAL};
112
113 let n = sexp.len();
114 match sexp.type_of() {
115 SEXPTYPE::NILSXP => Ok(RValue::Null),
116 SEXPTYPE::LGLSXP => Ok(RValue::Logical(
117 (0..n as isize)
118 .map(|i| {
119 let x = sexp.logical_elt(i);
120 (x != NA_LOGICAL).then_some(x != 0)
121 })
122 .collect(),
123 )),
124 SEXPTYPE::INTSXP => Ok(RValue::Integer(
125 (0..n as isize)
126 .map(|i| {
127 let x = sexp.integer_elt(i);
128 (x != NA_INTEGER).then_some(x)
129 })
130 .collect(),
131 )),
132 SEXPTYPE::REALSXP => Ok(RValue::Double(
134 (0..n as isize).map(|i| sexp.real_elt(i)).collect(),
135 )),
136 SEXPTYPE::CPLXSXP => Ok(RValue::Complex(
137 (0..n as isize).map(|i| sexp.complex_elt(i)).collect(),
138 )),
139 SEXPTYPE::STRSXP => Ok(RValue::Character(
140 (0..n as isize)
141 .map(|i| {
142 if sexp.string_elt(i).is_na_string() {
143 None
144 } else {
145 sexp.string_elt_str(i).map(str::to_string)
146 }
147 })
148 .collect(),
149 )),
150 SEXPTYPE::RAWSXP => Ok(RValue::Raw(unsafe { sexp.as_slice::<u8>() }.to_vec())),
152 SEXPTYPE::VECSXP => {
153 let names = sexp.get_names();
154 let mut pairs = Vec::with_capacity(n);
155 for i in 0..n as isize {
156 let name = if names.is_nil()
159 || !names.is_character()
160 || names.string_elt(i).is_na_string()
161 {
162 None
163 } else {
164 names
165 .string_elt_str(i)
166 .filter(|s| !s.is_empty())
167 .map(str::to_string)
168 };
169 pairs.push((name, RValue::try_from_sexp(sexp.vector_elt(i))?));
170 }
171 Ok(RValue::List(pairs))
172 }
173 other => Err(SexpError::InvalidValue(format!(
174 "RValue cannot represent SEXP of type {other:?} (only R data vectors are modelled)"
175 ))),
176 }
177 }
178}
179
180impl From<i32> for RValue {
185 fn from(v: i32) -> Self {
186 RValue::Integer(vec![Some(v)])
187 }
188}
189impl From<f64> for RValue {
190 fn from(v: f64) -> Self {
191 RValue::Double(vec![v])
192 }
193}
194impl From<bool> for RValue {
195 fn from(v: bool) -> Self {
196 RValue::Logical(vec![Some(v)])
197 }
198}
199impl From<String> for RValue {
200 fn from(v: String) -> Self {
201 RValue::Character(vec![Some(v)])
202 }
203}
204impl From<&str> for RValue {
205 fn from(v: &str) -> Self {
206 RValue::Character(vec![Some(v.to_string())])
207 }
208}
209impl From<Vec<i32>> for RValue {
210 fn from(v: Vec<i32>) -> Self {
211 RValue::Integer(v.into_iter().map(Some).collect())
212 }
213}
214impl From<Vec<f64>> for RValue {
215 fn from(v: Vec<f64>) -> Self {
216 RValue::Double(v)
217 }
218}
219impl From<Vec<bool>> for RValue {
220 fn from(v: Vec<bool>) -> Self {
221 RValue::Logical(v.into_iter().map(Some).collect())
222 }
223}
224impl From<Vec<String>> for RValue {
225 fn from(v: Vec<String>) -> Self {
226 RValue::Character(v.into_iter().map(Some).collect())
227 }
228}
229impl From<Vec<&str>> for RValue {
230 fn from(v: Vec<&str>) -> Self {
231 RValue::Character(v.into_iter().map(|s| Some(s.to_string())).collect())
232 }
233}
234
235impl From<Option<i32>> for RValue {
244 fn from(v: Option<i32>) -> Self {
245 RValue::Integer(vec![v])
246 }
247}
248impl From<Option<f64>> for RValue {
249 fn from(v: Option<f64>) -> Self {
250 RValue::Double(vec![v.unwrap_or(crate::altrep_traits::NA_REAL)])
251 }
252}
253impl From<Option<bool>> for RValue {
254 fn from(v: Option<bool>) -> Self {
255 RValue::Logical(vec![v])
256 }
257}
258impl From<Option<String>> for RValue {
259 fn from(v: Option<String>) -> Self {
260 RValue::Character(vec![v])
261 }
262}
263impl From<Option<&str>> for RValue {
264 fn from(v: Option<&str>) -> Self {
265 RValue::Character(vec![v.map(str::to_string)])
266 }
267}
268impl From<Vec<Option<i32>>> for RValue {
269 fn from(v: Vec<Option<i32>>) -> Self {
270 RValue::Integer(v)
271 }
272}
273impl From<Vec<Option<f64>>> for RValue {
274 fn from(v: Vec<Option<f64>>) -> Self {
275 RValue::Double(
276 v.into_iter()
277 .map(|x| x.unwrap_or(crate::altrep_traits::NA_REAL))
278 .collect(),
279 )
280 }
281}
282impl From<Vec<Option<bool>>> for RValue {
283 fn from(v: Vec<Option<bool>>) -> Self {
284 RValue::Logical(v)
285 }
286}
287impl From<Vec<Option<String>>> for RValue {
288 fn from(v: Vec<Option<String>>) -> Self {
289 RValue::Character(v)
290 }
291}
292impl From<Vec<Option<&str>>> for RValue {
293 fn from(v: Vec<Option<&str>>) -> Self {
294 RValue::Character(v.into_iter().map(|s| s.map(str::to_string)).collect())
295 }
296}
297
298impl From<i64> for RValue {
302 fn from(v: i64) -> Self {
303 match i32::try_from(v) {
304 Ok(n) if n != i32::MIN => RValue::Integer(vec![Some(n)]),
305 _ => RValue::Double(vec![v as f64]),
308 }
309 }
310}
311impl From<u32> for RValue {
312 fn from(v: u32) -> Self {
315 RValue::from(i64::from(v))
316 }
317}
318
319impl RValue {
324 pub fn sexptype(&self) -> SEXPTYPE {
326 match self {
327 RValue::Null => SEXPTYPE::NILSXP,
328 RValue::Logical(_) => SEXPTYPE::LGLSXP,
329 RValue::Integer(_) => SEXPTYPE::INTSXP,
330 RValue::Double(_) => SEXPTYPE::REALSXP,
331 RValue::Complex(_) => SEXPTYPE::CPLXSXP,
332 RValue::Character(_) => SEXPTYPE::STRSXP,
333 RValue::Raw(_) => SEXPTYPE::RAWSXP,
334 RValue::List(_) => SEXPTYPE::VECSXP,
335 }
336 }
337
338 pub fn is_null(&self) -> bool {
340 matches!(self, RValue::Null)
341 }
342
343 pub fn debug<T: std::fmt::Debug>(value: T) -> Self {
353 RValue::Character(vec![Some(format!("{value:?}"))])
354 }
355
356 pub fn as_i32(&self) -> Option<i32> {
362 match self {
363 RValue::Integer(v) if v.len() == 1 => v[0],
364 _ => None,
365 }
366 }
367
368 pub fn as_f64(&self) -> Option<f64> {
372 match self {
373 RValue::Double(v) if v.len() == 1 => {
374 let x = v[0];
375 (x.to_bits() != crate::altrep_traits::NA_REAL.to_bits()).then_some(x)
376 }
377 _ => None,
378 }
379 }
380
381 pub fn as_bool(&self) -> Option<bool> {
383 match self {
384 RValue::Logical(v) if v.len() == 1 => v[0],
385 _ => None,
386 }
387 }
388
389 pub fn as_str(&self) -> Option<&str> {
391 match self {
392 RValue::Character(v) if v.len() == 1 => v[0].as_deref(),
393 _ => None,
394 }
395 }
396}
397
398fn wrong_type(expected: SEXPTYPE, actual: &RValue) -> SexpError {
400 SexpError::Type(SexpTypeError {
401 expected,
402 actual: actual.sexptype(),
403 })
404}
405
406macro_rules! try_from_scalar_opt {
412 ($t:ty, $variant:ident, $ty:expr) => {
413 impl TryFrom<RValue> for $t {
414 type Error = SexpError;
415 fn try_from(value: RValue) -> Result<Self, SexpError> {
416 match value {
417 RValue::$variant(xs) => {
418 if xs.len() != 1 {
419 return Err(SexpError::Length(SexpLengthError {
420 expected: 1,
421 actual: xs.len(),
422 }));
423 }
424 xs.into_iter()
425 .next()
426 .unwrap()
427 .ok_or(SexpError::Na(SexpNaError { sexp_type: $ty }))
428 }
429 other => Err(wrong_type($ty, &other)),
430 }
431 }
432 }
433 };
434}
435try_from_scalar_opt!(i32, Integer, SEXPTYPE::INTSXP);
436try_from_scalar_opt!(bool, Logical, SEXPTYPE::LGLSXP);
437try_from_scalar_opt!(String, Character, SEXPTYPE::STRSXP);
438
439impl TryFrom<RValue> for f64 {
441 type Error = SexpError;
442 fn try_from(value: RValue) -> Result<Self, SexpError> {
443 match value {
444 RValue::Double(xs) => {
445 if xs.len() != 1 {
446 return Err(SexpError::Length(SexpLengthError {
447 expected: 1,
448 actual: xs.len(),
449 }));
450 }
451 let x = xs[0];
452 if x.to_bits() == crate::altrep_traits::NA_REAL.to_bits() {
453 Err(SexpError::Na(SexpNaError {
454 sexp_type: SEXPTYPE::REALSXP,
455 }))
456 } else {
457 Ok(x)
458 }
459 }
460 other => Err(wrong_type(SEXPTYPE::REALSXP, &other)),
461 }
462 }
463}
464
465macro_rules! try_from_vec {
467 ($t:ty, $variant:ident, $ty:expr) => {
468 impl TryFrom<RValue> for $t {
469 type Error = SexpError;
470 fn try_from(value: RValue) -> Result<Self, SexpError> {
471 match value {
472 RValue::$variant(xs) => Ok(xs),
473 other => Err(wrong_type($ty, &other)),
474 }
475 }
476 }
477 };
478}
479try_from_vec!(Vec<Option<bool>>, Logical, SEXPTYPE::LGLSXP);
480try_from_vec!(Vec<Option<i32>>, Integer, SEXPTYPE::INTSXP);
481try_from_vec!(Vec<f64>, Double, SEXPTYPE::REALSXP);
482try_from_vec!(Vec<Rcomplex>, Complex, SEXPTYPE::CPLXSXP);
483try_from_vec!(Vec<Option<String>>, Character, SEXPTYPE::STRSXP);
484try_from_vec!(Vec<u8>, Raw, SEXPTYPE::RAWSXP);
485try_from_vec!(Vec<(Option<String>, RValue)>, List, SEXPTYPE::VECSXP);
486
487#[cfg(test)]
490mod tests {
491 use super::*;
492
493 #[test]
496 fn as_scalar_accessors() {
497 assert_eq!(RValue::from(7i32).as_i32(), Some(7));
498 assert_eq!(RValue::from(1.5).as_f64(), Some(1.5));
499 assert_eq!(RValue::from(true).as_bool(), Some(true));
500 assert_eq!(RValue::from("hi").as_str(), Some("hi"));
501
502 assert_eq!(RValue::from("hi").as_i32(), None);
504 assert_eq!(RValue::Integer(vec![Some(1), Some(2)]).as_i32(), None);
506 assert_eq!(RValue::Integer(vec![None]).as_i32(), None);
508 assert_eq!(
509 RValue::Double(vec![crate::altrep_traits::NA_REAL]).as_f64(),
510 None
511 );
512 assert!(RValue::Null.is_null());
513 }
514
515 #[test]
516 fn try_from_scalar_ok_and_errors() {
517 assert_eq!(i32::try_from(RValue::from(7i32)).unwrap(), 7);
518 assert_eq!(f64::try_from(RValue::from(2.5)).unwrap(), 2.5);
519 assert!(!bool::try_from(RValue::from(false)).unwrap());
520 assert_eq!(String::try_from(RValue::from("x")).unwrap(), "x");
521
522 assert!(matches!(
524 i32::try_from(RValue::from("x")),
525 Err(SexpError::Type(_))
526 ));
527 assert!(matches!(
529 i32::try_from(RValue::Integer(vec![Some(1), Some(2)])),
530 Err(SexpError::Length(_))
531 ));
532 assert!(matches!(
534 i32::try_from(RValue::Integer(vec![None])),
535 Err(SexpError::Na(_))
536 ));
537 assert!(matches!(
538 f64::try_from(RValue::Double(vec![crate::altrep_traits::NA_REAL])),
539 Err(SexpError::Na(_))
540 ));
541 }
542
543 #[test]
544 fn from_option_scalars() {
545 assert!(matches!(RValue::from(Some(7_i32)), RValue::Integer(v) if v == vec![Some(7)]));
546 assert!(matches!(RValue::from(None::<i32>), RValue::Integer(v) if v == vec![None]));
547 assert!(matches!(RValue::from(Some(true)), RValue::Logical(v) if v == vec![Some(true)]));
548 assert!(matches!(RValue::from(None::<bool>), RValue::Logical(v) if v == vec![None]));
549 assert!(
550 matches!(RValue::from(Some("x")), RValue::Character(v) if v == vec![Some("x".to_string())])
551 );
552 assert!(matches!(RValue::from(None::<&str>), RValue::Character(v) if v == vec![None]));
553 assert!(
554 matches!(RValue::from(Some("y".to_string())), RValue::Character(v) if v == vec![Some("y".to_string())])
555 );
556
557 assert_eq!(RValue::from(Some(1.5_f64)).as_f64(), Some(1.5));
559 assert_eq!(RValue::from(None::<f64>).as_f64(), None);
560 }
561
562 #[test]
563 fn from_vec_option() {
564 assert!(
565 matches!(RValue::from(vec![Some(1_i32), None, Some(3)]), RValue::Integer(v) if v == vec![Some(1), None, Some(3)])
566 );
567 assert!(
568 matches!(RValue::from(vec![Some(true), None]), RValue::Logical(v) if v == vec![Some(true), None])
569 );
570 assert!(
571 matches!(RValue::from(vec![Some("a".to_string()), None]), RValue::Character(v) if v == vec![Some("a".to_string()), None])
572 );
573 assert!(
574 matches!(RValue::from(vec![Some("b"), None]), RValue::Character(v) if v == vec![Some("b".to_string()), None])
575 );
576
577 let RValue::Double(v) = RValue::from(vec![Some(0.5_f64), None]) else {
579 panic!("expected Double");
580 };
581 assert_eq!(v[0], 0.5);
582 assert_eq!(v[1].to_bits(), crate::altrep_traits::NA_REAL.to_bits());
583 }
584
585 #[test]
586 fn from_wide_integer_ladder() {
587 assert!(matches!(RValue::from(42_i64), RValue::Integer(v) if v == vec![Some(42)]));
589 assert!(
590 matches!(RValue::from(i32::MAX as i64), RValue::Integer(v) if v == vec![Some(i32::MAX)])
591 );
592 assert!(matches!(RValue::from(7_u32), RValue::Integer(v) if v == vec![Some(7)]));
593 assert!(matches!(RValue::from(i32::MIN as i64), RValue::Double(_)));
595 assert!(
597 matches!(RValue::from(i32::MAX as i64 + 1), RValue::Double(v) if v == vec![(i32::MAX as i64 + 1) as f64])
598 );
599 assert!(
601 matches!(RValue::from(u32::MAX), RValue::Double(v) if v == vec![f64::from(u32::MAX)])
602 );
603 }
604
605 #[test]
606 fn debug_stringifies() {
607 assert_eq!(RValue::debug(0..=100).as_str(), Some("0..=100"));
608 assert_eq!(RValue::debug(vec![1, 2]).as_str(), Some("[1, 2]"));
609 }
610
611 #[test]
612 fn try_from_whole_vector() {
613 let v: Vec<Option<i32>> = RValue::Integer(vec![Some(1), None]).try_into().unwrap();
614 assert_eq!(v, vec![Some(1), None]);
615
616 let raw: Vec<u8> = RValue::Raw(vec![1, 2, 3]).try_into().unwrap();
617 assert_eq!(raw, vec![1, 2, 3]);
618
619 let bad: Result<Vec<u8>, _> = RValue::from(1i32).try_into();
621 assert!(matches!(bad, Err(SexpError::Type(_))));
622 }
623}