1use super::*;
2use crate::scalar::Scalar;
3use crate::single_threaded;
4use extendr_ffi::{
5 cetype_t, R_BlankString, R_NaInt, R_NaReal, R_NaString, R_NilValue, Rcomplex, Rf_mkCharLenCE,
6 COMPLEX, INTEGER, LOGICAL, RAW, REAL, SET_STRING_ELT, SEXPTYPE,
7};
8mod repeat_into_robj;
9
10pub(crate) fn str_to_character(s: &str) -> SEXP {
17 unsafe {
18 if s.is_na() {
19 R_NaString
20 } else if s.is_empty() {
21 R_BlankString
22 } else {
23 single_threaded(|| {
24 Rf_mkCharLenCE(s.as_ptr().cast(), s.len() as i32, cetype_t::CE_UTF8)
26 })
27 }
28 }
29}
30
31impl From<()> for Robj {
33 fn from(_: ()) -> Self {
34 unsafe { Robj::from_sexp(R_NilValue) }
36 }
37}
38
39#[cfg(not(any(feature = "result_list", feature = "result_condition")))]
66impl<T, E> From<std::result::Result<T, E>> for Robj
67where
68 T: Into<Robj>,
69 E: std::fmt::Debug + std::fmt::Display,
70{
71 fn from(res: std::result::Result<T, E>) -> Self {
72 res.unwrap().into()
73 }
74}
75
76#[cfg(all(feature = "result_condition", not(feature = "result_list")))]
83impl<T, E> From<std::result::Result<T, E>> for Robj
84where
85 T: Into<Robj>,
86 E: Into<Robj>,
87{
88 fn from(res: std::result::Result<T, E>) -> Self {
89 use crate as extendr_api;
90 match res {
91 Ok(x) => x.into(),
92 Err(x) => {
93 let mut err = list!(message = "extendr_err", value = x.into());
94 err.set_class(["extendr_error", "error", "condition"])
95 .expect("internal error: failed to set class");
96 err.into()
97 }
98 }
99 }
100}
101
102#[cfg(feature = "result_list")]
109impl<T, E> From<std::result::Result<T, E>> for Robj
110where
111 T: Into<Robj>,
112 E: Into<Robj>,
113{
114 fn from(res: std::result::Result<T, E>) -> Self {
115 use crate as extendr_api;
116 let mut result = match res {
117 Ok(x) => list!(ok = x.into(), err = NULL),
118 Err(x) => {
119 let err_robj = x.into();
120 if err_robj.is_null() {
121 panic!("Internal error: result_list not allowed to return NULL as err-value")
122 }
123 list!(ok = NULL, err = err_robj)
124 }
125 };
126 result
127 .set_class(&["extendr_result"])
128 .expect("Internal error: failed to set class");
129 result.into()
130 }
131}
132
133impl From<Error> for Robj {
135 fn from(res: Error) -> Self {
136 res.to_string().into()
137 }
138}
139impl From<Error> for String {
140 fn from(res: Error) -> Self {
141 res.to_string()
142 }
143}
144
145impl From<&Robj> for Robj {
147 fn from(val: &Robj) -> Self {
150 unsafe { Robj::from_sexp(val.get()) }
151 }
152}
153
154pub trait IntoRobj {
159 fn into_robj(self) -> Robj;
160}
161
162impl<T> IntoRobj for T
163where
164 Robj: From<T>,
165{
166 fn into_robj(self) -> Robj {
167 self.into()
168 }
169}
170
171pub trait ToVectorValue {
175 fn sexptype() -> SEXPTYPE {
176 SEXPTYPE::NILSXP
177 }
178
179 fn to_real(&self) -> f64
180 where
181 Self: Sized,
182 {
183 0.
184 }
185
186 fn to_complex(&self) -> Rcomplex
187 where
188 Self: Sized,
189 {
190 Rcomplex { r: 0., i: 0. }
191 }
192
193 fn to_integer(&self) -> i32
194 where
195 Self: Sized,
196 {
197 i32::MIN
198 }
199
200 fn to_logical(&self) -> i32
201 where
202 Self: Sized,
203 {
204 i32::MIN
205 }
206
207 fn to_raw(&self) -> u8
208 where
209 Self: Sized,
210 {
211 0
212 }
213
214 fn to_sexp(&self) -> SEXP
215 where
216 Self: Sized,
217 {
218 unsafe { R_NilValue }
219 }
220}
221
222macro_rules! impl_real_tvv {
223 ($t: ty) => {
224 impl ToVectorValue for $t {
225 fn sexptype() -> SEXPTYPE {
226 SEXPTYPE::REALSXP
227 }
228
229 fn to_real(&self) -> f64 {
230 *self as f64
231 }
232 }
233
234 impl ToVectorValue for &$t {
235 fn sexptype() -> SEXPTYPE {
236 SEXPTYPE::REALSXP
237 }
238
239 fn to_real(&self) -> f64 {
240 **self as f64
241 }
242 }
243
244 impl ToVectorValue for Option<$t> {
245 fn sexptype() -> SEXPTYPE {
246 SEXPTYPE::REALSXP
247 }
248
249 fn to_real(&self) -> f64 {
250 if self.is_some() {
251 self.unwrap() as f64
252 } else {
253 unsafe { R_NaReal }
254 }
255 }
256 }
257 };
258}
259
260impl_real_tvv!(f64);
261impl_real_tvv!(f32);
262
263impl_real_tvv!(i64);
266impl_real_tvv!(u32);
267impl_real_tvv!(u64);
268impl_real_tvv!(usize);
269
270macro_rules! impl_complex_tvv {
271 ($t: ty) => {
272 impl ToVectorValue for $t {
273 fn sexptype() -> SEXPTYPE {
274 SEXPTYPE::CPLXSXP
275 }
276
277 fn to_complex(&self) -> Rcomplex {
278 unsafe { std::mem::transmute(*self) }
279 }
280 }
281
282 impl ToVectorValue for &$t {
283 fn sexptype() -> SEXPTYPE {
284 SEXPTYPE::CPLXSXP
285 }
286
287 fn to_complex(&self) -> Rcomplex {
288 unsafe { std::mem::transmute(**self) }
289 }
290 }
291 };
292}
293
294impl_complex_tvv!(c64);
295impl_complex_tvv!(Rcplx);
296impl_complex_tvv!((f64, f64));
297
298macro_rules! impl_integer_tvv {
299 ($t: ty) => {
300 impl ToVectorValue for $t {
301 fn sexptype() -> SEXPTYPE {
302 SEXPTYPE::INTSXP
303 }
304
305 fn to_integer(&self) -> i32 {
306 *self as i32
307 }
308 }
309
310 impl ToVectorValue for &$t {
311 fn sexptype() -> SEXPTYPE {
312 SEXPTYPE::INTSXP
313 }
314
315 fn to_integer(&self) -> i32 {
316 **self as i32
317 }
318 }
319
320 impl ToVectorValue for Option<$t> {
321 fn sexptype() -> SEXPTYPE {
322 SEXPTYPE::INTSXP
323 }
324
325 fn to_integer(&self) -> i32 {
326 if self.is_some() {
327 self.unwrap() as i32
328 } else {
329 unsafe { R_NaInt }
330 }
331 }
332 }
333 };
334}
335
336impl_integer_tvv!(i8);
337impl_integer_tvv!(i16);
338impl_integer_tvv!(i32);
339impl_integer_tvv!(u16);
340
341impl ToVectorValue for u8 {
342 fn sexptype() -> SEXPTYPE {
343 SEXPTYPE::RAWSXP
344 }
345
346 fn to_raw(&self) -> u8 {
347 *self
348 }
349}
350
351impl ToVectorValue for &u8 {
352 fn sexptype() -> SEXPTYPE {
353 SEXPTYPE::RAWSXP
354 }
355
356 fn to_raw(&self) -> u8 {
357 **self
358 }
359}
360
361macro_rules! impl_str_tvv {
362 ($t: ty) => {
363 impl ToVectorValue for $t {
364 fn sexptype() -> SEXPTYPE {
365 SEXPTYPE::STRSXP
366 }
367
368 fn to_sexp(&self) -> SEXP
369 where
370 Self: Sized,
371 {
372 str_to_character(self.as_ref())
373 }
374 }
375
376 impl ToVectorValue for &$t {
377 fn sexptype() -> SEXPTYPE {
378 SEXPTYPE::STRSXP
379 }
380
381 fn to_sexp(&self) -> SEXP
382 where
383 Self: Sized,
384 {
385 str_to_character(self.as_ref())
386 }
387 }
388
389 impl ToVectorValue for Option<$t> {
390 fn sexptype() -> SEXPTYPE {
391 SEXPTYPE::STRSXP
392 }
393
394 fn to_sexp(&self) -> SEXP
395 where
396 Self: Sized,
397 {
398 if let Some(s) = self {
399 str_to_character(s.as_ref())
400 } else {
401 unsafe { R_NaString }
402 }
403 }
404 }
405 };
406}
407
408impl_str_tvv! {&str}
409impl_str_tvv! {String}
410
411impl ToVectorValue for Rstr {
412 fn sexptype() -> SEXPTYPE {
413 SEXPTYPE::STRSXP
414 }
415
416 fn to_sexp(&self) -> SEXP
417 where
418 Self: Sized,
419 {
420 unsafe { self.get() }
421 }
422}
423
424impl ToVectorValue for &Rstr {
425 fn sexptype() -> SEXPTYPE {
426 SEXPTYPE::STRSXP
427 }
428
429 fn to_sexp(&self) -> SEXP
430 where
431 Self: Sized,
432 {
433 unsafe { self.get() }
434 }
435}
436
437impl ToVectorValue for Option<Rstr> {
438 fn sexptype() -> SEXPTYPE {
439 SEXPTYPE::STRSXP
440 }
441
442 fn to_sexp(&self) -> SEXP
443 where
444 Self: Sized,
445 {
446 if let Some(s) = self {
447 unsafe { s.get() }
448 } else {
449 unsafe { R_NaString }
450 }
451 }
452}
453
454impl TryFrom<&Robj> for Rstr {
455 type Error = crate::Error;
456
457 fn try_from(robj: &Robj) -> Result<Self> {
458 let sexptype = robj.sexptype();
459 if let SEXPTYPE::STRSXP = sexptype {
460 if robj.len() == 1 {
461 let strs = Strings::try_from(robj)?;
462 Ok(strs.elt(0))
463 } else {
464 Err(Error::ExpectedRstr(robj.clone()))
465 }
466 } else if let SEXPTYPE::CHARSXP = sexptype {
467 Ok(Rstr { robj: robj.clone() })
468 } else {
469 Err(Error::ExpectedRstr(robj.clone()))
470 }
471 }
472}
473
474impl TryFrom<Robj> for Rstr {
475 type Error = crate::Error;
476
477 fn try_from(value: Robj) -> std::result::Result<Self, Self::Error> {
478 Self::try_from(&value)
479 }
480}
481
482impl GetSexp for Rstr {
483 unsafe fn get(&self) -> SEXP {
484 self.robj.get()
485 }
486
487 unsafe fn get_mut(&mut self) -> SEXP {
488 self.robj.get_mut()
489 }
490
491 fn as_robj(&self) -> &Robj {
492 &self.robj
493 }
494
495 fn as_robj_mut(&mut self) -> &mut Robj {
496 &mut self.robj
497 }
498}
499
500impl Length for Rstr {}
502impl Types for Rstr {}
503impl Conversions for Rstr {}
504impl Rinternals for Rstr {}
505impl Slices for Rstr {}
506impl Operators for Rstr {}
507
508impl ToVectorValue for bool {
509 fn sexptype() -> SEXPTYPE {
510 SEXPTYPE::LGLSXP
511 }
512
513 fn to_logical(&self) -> i32
514 where
515 Self: Sized,
516 {
517 *self as i32
518 }
519}
520
521impl ToVectorValue for &bool {
522 fn sexptype() -> SEXPTYPE {
523 SEXPTYPE::LGLSXP
524 }
525
526 fn to_logical(&self) -> i32
527 where
528 Self: Sized,
529 {
530 **self as i32
531 }
532}
533
534impl ToVectorValue for Rbool {
535 fn sexptype() -> SEXPTYPE {
536 SEXPTYPE::LGLSXP
537 }
538
539 fn to_logical(&self) -> i32
540 where
541 Self: Sized,
542 {
543 self.inner()
544 }
545}
546
547impl ToVectorValue for &Rbool {
548 fn sexptype() -> SEXPTYPE {
549 SEXPTYPE::LGLSXP
550 }
551
552 fn to_logical(&self) -> i32
553 where
554 Self: Sized,
555 {
556 self.inner()
557 }
558}
559
560impl ToVectorValue for Option<bool> {
561 fn sexptype() -> SEXPTYPE {
562 SEXPTYPE::LGLSXP
563 }
564
565 fn to_logical(&self) -> i32 {
566 if self.is_some() {
567 self.unwrap() as i32
568 } else {
569 unsafe { R_NaInt }
570 }
571 }
572}
573
574fn fixed_size_collect<I>(iter: I, len: usize) -> Robj
576where
577 I: Iterator,
578 I: Sized,
579 I::Item: ToVectorValue,
580{
581 single_threaded(|| unsafe {
582 let sexptype = I::Item::sexptype();
584 if sexptype != SEXPTYPE::NILSXP {
585 let res = Robj::alloc_vector(sexptype, len);
586 let sexp = res.get();
587 match sexptype {
588 SEXPTYPE::REALSXP => {
589 let ptr = REAL(sexp);
590 for (i, v) in iter.enumerate() {
591 *ptr.add(i) = v.to_real();
592 }
593 }
594 SEXPTYPE::CPLXSXP => {
595 let ptr = COMPLEX(sexp);
596 for (i, v) in iter.enumerate() {
597 *ptr.add(i) = v.to_complex();
598 }
599 }
600 SEXPTYPE::INTSXP => {
601 let ptr = INTEGER(sexp);
602 for (i, v) in iter.enumerate() {
603 *ptr.add(i) = v.to_integer();
604 }
605 }
606 SEXPTYPE::LGLSXP => {
607 let ptr = LOGICAL(sexp);
608 for (i, v) in iter.enumerate() {
609 *ptr.add(i) = v.to_logical();
610 }
611 }
612 SEXPTYPE::STRSXP => {
613 for (i, v) in iter.enumerate() {
614 SET_STRING_ELT(sexp, i as isize, v.to_sexp());
615 }
616 }
617 SEXPTYPE::RAWSXP => {
618 let ptr = RAW(sexp);
619 for (i, v) in iter.enumerate() {
620 *ptr.add(i) = v.to_raw();
621 }
622 }
623 _ => {
624 panic!("unexpected SEXPTYPE in collect_robj");
625 }
626 }
627 res
628 } else {
629 Robj::from(())
630 }
631 })
632}
633
634pub trait RobjItertools: Iterator {
636 fn collect_robj(self) -> Robj
659 where
660 Self: Iterator,
661 Self: Sized,
662 Self::Item: ToVectorValue,
663 {
664 if let (len, Some(max)) = self.size_hint() {
665 if len == max {
666 return fixed_size_collect(self, len);
667 }
668 }
669 let vec: Vec<_> = self.collect();
671 assert!(vec.iter().size_hint() == (vec.len(), Some(vec.len())));
672 vec.into_iter().collect_robj()
673 }
674
675 fn collect_rarray<const LEN: usize>(self, dims: [usize; LEN]) -> Result<RArray<Self::Item, LEN>>
682 where
683 Self: Iterator,
684 Self: Sized,
685 Self::Item: ToVectorValue,
686 Robj: for<'a> AsTypedSlice<'a, Self::Item>,
687 {
688 let mut vector = self.collect_robj();
689 let prod = dims.iter().product::<usize>();
690 if prod != vector.len() {
691 return Err(Error::Other(format!(
692 "The vector length ({}) does not match the length implied by the dimensions ({})",
693 vector.len(),
694 prod
695 )));
696 }
697 vector.set_attrib(wrapper::symbol::dim_symbol(), dims.iter().collect_robj())?;
698 let _data = vector.as_typed_slice().ok_or(Error::Other(
699 "Unknown error in converting to slice".to_string(),
700 ))?;
701 Ok(RArray::from_parts(vector))
702 }
703}
704
705impl<T> RobjItertools for T where T: Iterator {}
707
708impl<T> From<T> for Robj
710where
711 T: ToVectorValue,
712{
713 fn from(scalar: T) -> Self {
714 Some(scalar).into_iter().collect_robj()
715 }
716}
717
718macro_rules! impl_from_as_iterator {
719 ($t: ty) => {
720 impl<T> From<$t> for Robj
721 where
722 $t: RobjItertools,
723 <$t as Iterator>::Item: ToVectorValue,
724 T: ToVectorValue,
725 {
726 fn from(val: $t) -> Self {
727 val.collect_robj()
728 }
729 }
730 };
731}
732
733impl<T, const N: usize> From<[T; N]> for Robj
745where
746 T: ToVectorValue,
747{
748 fn from(val: [T; N]) -> Self {
749 fixed_size_collect(val.into_iter(), N)
750 }
751}
752
753impl<'a, T, const N: usize> From<&'a [T; N]> for Robj
754where
755 Self: 'a,
756 &'a T: ToVectorValue + 'a,
757{
758 fn from(val: &'a [T; N]) -> Self {
759 fixed_size_collect(val.iter(), N)
760 }
761}
762
763impl<'a, T, const N: usize> From<&'a mut [T; N]> for Robj
764where
765 Self: 'a,
766 &'a mut T: ToVectorValue + 'a,
767{
768 fn from(val: &'a mut [T; N]) -> Self {
769 fixed_size_collect(val.iter_mut(), N)
770 }
771}
772
773impl<T: ToVectorValue + Clone> From<&Vec<T>> for Robj {
774 fn from(value: &Vec<T>) -> Self {
775 let len = value.len();
776 fixed_size_collect(value.iter().cloned(), len)
777 }
778}
779
780impl<T: ToVectorValue> From<Vec<T>> for Robj {
781 fn from(value: Vec<T>) -> Self {
782 let len = value.len();
783 fixed_size_collect(value.into_iter(), len)
784 }
785}
786
787impl<'a, T> From<&'a [T]> for Robj
788where
789 Self: 'a,
790 T: 'a,
791 &'a T: ToVectorValue,
792{
793 fn from(val: &'a [T]) -> Self {
794 val.iter().collect_robj()
795 }
796}
797
798impl_from_as_iterator! {Range<T>}
799impl_from_as_iterator! {RangeInclusive<T>}
800
801impl From<Vec<Robj>> for Robj {
802 fn from(val: Vec<Robj>) -> Self {
804 Self::from(&val)
805 }
806}
807
808impl From<&Vec<Robj>> for Robj {
809 fn from(val: &Vec<Robj>) -> Self {
810 List::from_values(val.iter()).into()
811 }
812}
813
814#[cfg(test)]
815mod test {
816 use super::*;
817 use crate as extendr_api;
818
819 #[test]
820 fn test_vec_rint_to_robj() {
821 test! {
822 let int_vec = vec![3,4,0,-2];
823 let int_vec_robj: Robj = int_vec.clone().into();
824 assert_eq!(int_vec_robj.as_integer_slice().unwrap(), &int_vec);
826
827 let rint_vec = vec![Rint::from(3), Rint::from(4), Rint::from(0), Rint::from(-2)];
828 let rint_vec_robj: Robj = rint_vec.into();
829 assert_eq!(rint_vec_robj.as_integer_slice().unwrap(), &int_vec);
831 }
832 }
833
834 #[test]
835 fn test_collect_rarray_matrix() {
836 test! {
837 let rmat = (1i32..=16).collect_rarray([4, 4]);
839 assert!(rmat.is_ok());
840 assert_eq!(Robj::from(rmat), R!("matrix(1:16, nrow=4)").unwrap());
841 }
842 }
843
844 #[test]
845 fn test_collect_rarray_tensor() {
846 test! {
847 let rmat = (1i32..=16).collect_rarray([2, 4, 2]);
849 assert!(rmat.is_ok());
850 assert_eq!(Robj::from(rmat), R!("array(1:16, dim=c(2, 4, 2))").unwrap());
851 }
852 }
853
854 #[test]
855 fn test_collect_rarray_matrix_failure() {
856 test! {
857 let rmat = (1i32..=16).collect_rarray([3, 3]);
859 assert!(rmat.is_err());
860 let msg = rmat.unwrap_err().to_string();
861 assert!(msg.contains('9'));
862 assert!(msg.contains("dimension"));
863 }
864 }
865
866 #[test]
867 fn test_collect_tensor_failure() {
868 test! {
869 let rmat = (1i32..=16).collect_rarray([3, 3, 3]);
871 assert!(rmat.is_err());
872 let msg = rmat.unwrap_err().to_string();
873 assert!(msg.contains("27"));
874 assert!(msg.contains("dimension"));
875 }
876 }
877
878 #[test]
879 #[cfg(all(feature = "result_condition", not(feature = "result_list")))]
880 fn test_result_condition() {
881 use crate::prelude::*;
882 fn my_err_f() -> std::result::Result<f64, f64> {
883 Err(42.0) }
885
886 test! {
887 assert_eq!(
888 r!(my_err_f()),
889 R!(
890 "structure(list(message = 'extendr_err',
891 value = 42.0), class = c('extendr_error', 'error', 'condition'))"
892 ).unwrap()
893 );
894 }
895 }
896
897 #[test]
898 #[cfg(feature = "result_list")]
899 fn test_result_list() {
900 use crate::prelude::*;
901 fn my_err_f() -> std::result::Result<f64, String> {
902 Err("We have water in the engine room!".to_string())
903 }
904
905 fn my_ok_f() -> std::result::Result<f64, String> {
906 Ok(123.123)
907 }
908
909 test! {
910 assert_eq!(
911 r!(my_err_f()),
912 R!("x=list(ok=NULL, err='We have water in the engine room!')
913 class(x)='extendr_result'
914 x"
915 ).unwrap()
916 );
917 assert_eq!(
918 r!(my_ok_f()),
919 R!("x = list(ok=123.123, err=NULL)
920 class(x)='extendr_result'
921 x"
922 ).unwrap()
923 );
924 }
925 }
926}