1use crate::coerce::{CoerceError, TryCoerce};
51use crate::into_r::IntoR;
52use crate::{RLogical, SEXP};
53use std::fmt;
54
55#[derive(Debug, Clone, PartialEq, Eq)]
59pub enum StorageCoerceError {
60 Unsupported {
62 from: &'static str,
64 to: &'static str,
66 },
67 OutOfRange {
69 from: &'static str,
71 to: &'static str,
73 index: Option<usize>,
75 },
76 NonFinite {
78 to: &'static str,
80 index: Option<usize>,
82 },
83 PrecisionLoss {
85 to: &'static str,
87 index: Option<usize>,
89 },
90 NotIntegral {
92 to: &'static str,
94 index: Option<usize>,
96 },
97 MissingValue {
99 to: &'static str,
101 index: Option<usize>,
103 },
104 InvalidUtf8 {
106 index: Option<usize>,
108 },
109}
110
111impl fmt::Display for StorageCoerceError {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 match self {
114 StorageCoerceError::Unsupported { from, to } => {
115 write!(f, "cannot convert {} to {}", from, to)
116 }
117 StorageCoerceError::OutOfRange { from, to, index } => {
118 if let Some(i) = index {
119 write!(f, "value at index {} out of range for {} → {}", i, from, to)
120 } else {
121 write!(f, "value out of range for {} → {}", from, to)
122 }
123 }
124 StorageCoerceError::NonFinite { to, index } => {
125 if let Some(i) = index {
126 write!(
127 f,
128 "non-finite value at index {} cannot convert to {}",
129 i, to
130 )
131 } else {
132 write!(f, "non-finite value cannot convert to {}", to)
133 }
134 }
135 StorageCoerceError::PrecisionLoss { to, index } => {
136 if let Some(i) = index {
137 write!(
138 f,
139 "value at index {} would lose precision converting to {}",
140 i, to
141 )
142 } else {
143 write!(f, "value would lose precision converting to {}", to)
144 }
145 }
146 StorageCoerceError::NotIntegral { to, index } => {
147 if let Some(i) = index {
148 write!(
149 f,
150 "non-integral value at index {} cannot convert to {}",
151 i, to
152 )
153 } else {
154 write!(f, "non-integral value cannot convert to {}", to)
155 }
156 }
157 StorageCoerceError::MissingValue { to, index } => {
158 if let Some(i) = index {
159 write!(f, "missing value at index {} cannot convert to {}", i, to)
160 } else {
161 write!(f, "missing value cannot convert to {}", to)
162 }
163 }
164 StorageCoerceError::InvalidUtf8 { index } => {
165 if let Some(i) = index {
166 write!(f, "invalid UTF-8 at index {}", i)
167 } else {
168 write!(f, "invalid UTF-8")
169 }
170 }
171 }
172 }
173}
174
175impl std::error::Error for StorageCoerceError {}
176
177impl StorageCoerceError {
178 #[inline]
180 pub fn at_index(self, idx: usize) -> Self {
181 match self {
182 StorageCoerceError::OutOfRange { from, to, .. } => StorageCoerceError::OutOfRange {
183 from,
184 to,
185 index: Some(idx),
186 },
187 StorageCoerceError::NonFinite { to, .. } => StorageCoerceError::NonFinite {
188 to,
189 index: Some(idx),
190 },
191 StorageCoerceError::PrecisionLoss { to, .. } => StorageCoerceError::PrecisionLoss {
192 to,
193 index: Some(idx),
194 },
195 StorageCoerceError::NotIntegral { to, .. } => StorageCoerceError::NotIntegral {
196 to,
197 index: Some(idx),
198 },
199 StorageCoerceError::MissingValue { to, .. } => StorageCoerceError::MissingValue {
200 to,
201 index: Some(idx),
202 },
203 StorageCoerceError::InvalidUtf8 { .. } => {
204 StorageCoerceError::InvalidUtf8 { index: Some(idx) }
205 }
206 other => other,
207 }
208 }
209}
210pub trait IntoRAs<Target> {
242 fn into_r_as(self) -> Result<SEXP, StorageCoerceError>;
244}
245#[inline]
251fn try_coerce_scalar<T, R>(
252 value: T,
253 from: &'static str,
254 to: &'static str,
255) -> Result<R, StorageCoerceError>
256where
257 T: TryCoerce<R>,
258 T::Error: Into<CoerceErrorKind>,
259{
260 value
261 .try_coerce()
262 .map_err(|e| map_coerce_error(e.into(), from, to))
263}
264
265#[derive(Debug)]
267enum CoerceErrorKind {
268 Overflow,
269 PrecisionLoss,
270 NaN,
271 Infallible,
272}
273
274impl From<CoerceError> for CoerceErrorKind {
275 fn from(e: CoerceError) -> Self {
276 match e {
277 CoerceError::Overflow => CoerceErrorKind::Overflow,
278 CoerceError::PrecisionLoss => CoerceErrorKind::PrecisionLoss,
279 CoerceError::NaN => CoerceErrorKind::NaN,
280 CoerceError::Zero => CoerceErrorKind::Overflow, }
282 }
283}
284
285impl From<std::convert::Infallible> for CoerceErrorKind {
286 fn from(_: std::convert::Infallible) -> Self {
287 CoerceErrorKind::Infallible
288 }
289}
290
291fn map_coerce_error(
292 kind: CoerceErrorKind,
293 from: &'static str,
294 to: &'static str,
295) -> StorageCoerceError {
296 match kind {
297 CoerceErrorKind::Overflow => StorageCoerceError::OutOfRange {
298 from,
299 to,
300 index: None,
301 },
302 CoerceErrorKind::PrecisionLoss => StorageCoerceError::PrecisionLoss { to, index: None },
303 CoerceErrorKind::NaN => StorageCoerceError::NonFinite { to, index: None },
304 CoerceErrorKind::Infallible => unreachable!(),
305 }
306}
307macro_rules! impl_into_r_as_scalar {
312 ($target:ty, $target_name:literal; $from:ty, $from_name:literal) => {
313 impl IntoRAs<$target> for $from {
314 #[inline]
315 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
316 let v: $target = try_coerce_scalar(self, $from_name, $target_name)?;
317 Ok(v.into_sexp())
318 }
319 }
320 };
321}
322
323impl IntoRAs<i32> for i32 {
325 #[inline]
326 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
327 Ok(self.into_sexp())
328 }
329}
330
331impl_into_r_as_scalar!(i32, "i32"; i8, "i8");
333impl_into_r_as_scalar!(i32, "i32"; i16, "i16");
334impl_into_r_as_scalar!(i32, "i32"; u8, "u8");
335impl_into_r_as_scalar!(i32, "i32"; u16, "u16");
336
337impl_into_r_as_scalar!(i32, "i32"; i64, "i64");
339impl_into_r_as_scalar!(i32, "i32"; isize, "isize");
340impl_into_r_as_scalar!(i32, "i32"; u32, "u32");
341impl_into_r_as_scalar!(i32, "i32"; u64, "u64");
342impl_into_r_as_scalar!(i32, "i32"; usize, "usize");
343
344impl_into_r_as_scalar!(i32, "i32"; f32, "f32");
346impl_into_r_as_scalar!(i32, "i32"; f64, "f64");
347
348impl IntoRAs<i32> for bool {
350 #[inline]
351 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
352 Ok((self as i32).into_sexp())
353 }
354}
355impl IntoRAs<f64> for f64 {
361 #[inline]
362 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
363 if !self.is_finite() {
364 return Err(StorageCoerceError::NonFinite {
365 to: "f64",
366 index: None,
367 });
368 }
369 Ok(self.into_sexp())
370 }
371}
372
373impl IntoRAs<f64> for f32 {
375 #[inline]
376 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
377 if !self.is_finite() {
378 return Err(StorageCoerceError::NonFinite {
379 to: "f64",
380 index: None,
381 });
382 }
383 Ok((self as f64).into_sexp())
384 }
385}
386
387impl IntoRAs<f64> for i8 {
389 #[inline]
390 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
391 Ok((self as f64).into_sexp())
392 }
393}
394
395impl IntoRAs<f64> for i16 {
396 #[inline]
397 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
398 Ok((self as f64).into_sexp())
399 }
400}
401
402impl IntoRAs<f64> for i32 {
403 #[inline]
404 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
405 if self == crate::altrep_traits::NA_INTEGER {
409 return Err(StorageCoerceError::MissingValue {
410 to: "f64",
411 index: None,
412 });
413 }
414 Ok((self as f64).into_sexp())
415 }
416}
417
418impl IntoRAs<f64> for u8 {
419 #[inline]
420 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
421 Ok((self as f64).into_sexp())
422 }
423}
424
425impl IntoRAs<f64> for u16 {
426 #[inline]
427 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
428 Ok((self as f64).into_sexp())
429 }
430}
431
432impl IntoRAs<f64> for u32 {
433 #[inline]
434 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
435 Ok((self as f64).into_sexp())
436 }
437}
438
439impl_into_r_as_scalar!(f64, "f64"; i64, "i64");
441impl_into_r_as_scalar!(f64, "f64"; u64, "u64");
442impl_into_r_as_scalar!(f64, "f64"; isize, "isize");
443impl_into_r_as_scalar!(f64, "f64"; usize, "usize");
444
445impl IntoRAs<f64> for bool {
447 #[inline]
448 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
449 Ok((if self { 1.0 } else { 0.0 }).into_sexp())
450 }
451}
452impl IntoRAs<u8> for u8 {
458 #[inline]
459 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
460 Ok(self.into_sexp())
461 }
462}
463
464impl_into_r_as_scalar!(u8, "u8"; i8, "i8");
466impl_into_r_as_scalar!(u8, "u8"; i16, "i16");
467impl_into_r_as_scalar!(u8, "u8"; i32, "i32");
468impl_into_r_as_scalar!(u8, "u8"; i64, "i64");
469impl_into_r_as_scalar!(u8, "u8"; isize, "isize");
470impl_into_r_as_scalar!(u8, "u8"; u16, "u16");
471impl_into_r_as_scalar!(u8, "u8"; u32, "u32");
472impl_into_r_as_scalar!(u8, "u8"; u64, "u64");
473impl_into_r_as_scalar!(u8, "u8"; usize, "usize");
474impl_into_r_as_scalar!(u8, "u8"; f32, "f32");
475impl_into_r_as_scalar!(u8, "u8"; f64, "f64");
476impl IntoRAs<RLogical> for bool {
481 #[inline]
482 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
483 Ok(self.into_sexp())
484 }
485}
486
487impl IntoRAs<RLogical> for RLogical {
488 #[inline]
489 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
490 Ok(self.into_sexp())
491 }
492}
493
494impl IntoRAs<RLogical> for i32 {
496 #[inline]
497 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
498 match self {
499 0 => Ok(false.into_sexp()),
500 1 => Ok(true.into_sexp()),
501 crate::altrep_traits::NA_INTEGER => Ok(RLogical::NA.into_sexp()),
502 _ => Err(StorageCoerceError::OutOfRange {
503 from: "i32",
504 to: "RLogical",
505 index: None,
506 }),
507 }
508 }
509}
510impl IntoRAs<String> for String {
515 #[inline]
516 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
517 Ok(self.into_sexp())
518 }
519}
520
521impl IntoRAs<String> for &str {
522 #[inline]
523 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
524 Ok(self.into_sexp())
525 }
526}
527
528impl IntoRAs<String> for f64 {
530 #[inline]
531 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
532 let s = if self.is_nan() {
533 "NaN".to_string()
534 } else if self.is_infinite() {
535 if self.is_sign_positive() {
536 "Inf".to_string()
537 } else {
538 "-Inf".to_string()
539 }
540 } else {
541 self.to_string()
542 };
543 Ok(s.into_sexp())
544 }
545}
546
547impl IntoRAs<String> for f32 {
548 #[inline]
549 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
550 <f64 as IntoRAs<String>>::into_r_as(self as f64)
551 }
552}
553
554impl IntoRAs<String> for i32 {
555 #[inline]
556 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
557 Ok(self.to_string().into_sexp())
558 }
559}
560
561impl IntoRAs<String> for i64 {
562 #[inline]
563 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
564 Ok(self.to_string().into_sexp())
565 }
566}
567
568impl IntoRAs<String> for bool {
569 #[inline]
570 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
571 Ok((if self { "TRUE" } else { "FALSE" }).into_sexp())
572 }
573}
574
575impl IntoRAs<String> for RLogical {
576 #[inline]
577 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
578 let s = match self.to_option_bool() {
579 None => "NA",
580 Some(true) => "TRUE",
581 Some(false) => "FALSE",
582 };
583 Ok(s.into_sexp())
584 }
585}
586macro_rules! impl_vec_into_r_as {
591 ($target:ty, $target_name:literal; $from:ty, $from_name:literal) => {
592 impl IntoRAs<$target> for Vec<$from> {
593 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
594 let mut result = Vec::with_capacity(self.len());
595 for (i, val) in self.into_iter().enumerate() {
596 let v: $target = try_coerce_scalar(val, $from_name, $target_name)
597 .map_err(|e| e.at_index(i))?;
598 result.push(v);
599 }
600 Ok(result.into_sexp())
601 }
602 }
603
604 impl IntoRAs<$target> for &[$from] {
605 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
606 let mut result = Vec::with_capacity(self.len());
607 for (i, &val) in self.iter().enumerate() {
608 let v: $target = try_coerce_scalar(val, $from_name, $target_name)
609 .map_err(|e| e.at_index(i))?;
610 result.push(v);
611 }
612 Ok(result.into_sexp())
613 }
614 }
615 };
616}
617
618impl IntoRAs<i32> for Vec<i32> {
620 #[inline]
621 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
622 Ok(self.into_sexp())
623 }
624}
625
626impl IntoRAs<i32> for &[i32] {
627 #[inline]
628 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
629 Ok(self.into_sexp())
630 }
631}
632
633impl_vec_into_r_as!(i32, "i32"; i8, "i8");
634impl_vec_into_r_as!(i32, "i32"; i16, "i16");
635impl_vec_into_r_as!(i32, "i32"; u8, "u8");
636impl_vec_into_r_as!(i32, "i32"; u16, "u16");
637impl_vec_into_r_as!(i32, "i32"; i64, "i64");
638impl_vec_into_r_as!(i32, "i32"; isize, "isize");
639impl_vec_into_r_as!(i32, "i32"; u32, "u32");
640impl_vec_into_r_as!(i32, "i32"; u64, "u64");
641impl_vec_into_r_as!(i32, "i32"; usize, "usize");
642impl_vec_into_r_as!(i32, "i32"; f32, "f32");
643impl_vec_into_r_as!(i32, "i32"; f64, "f64");
644
645impl IntoRAs<i32> for Vec<bool> {
647 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
648 let result: Vec<i32> = self.into_iter().map(|b| b as i32).collect();
649 Ok(result.into_sexp())
650 }
651}
652
653impl IntoRAs<i32> for &[bool] {
654 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
655 let result: Vec<i32> = self.iter().map(|&b| b as i32).collect();
656 Ok(result.into_sexp())
657 }
658}
659impl IntoRAs<f64> for Vec<f64> {
665 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
666 for (i, &val) in self.iter().enumerate() {
667 if !val.is_finite() {
668 return Err(StorageCoerceError::NonFinite {
669 to: "f64",
670 index: Some(i),
671 });
672 }
673 }
674 Ok(self.into_sexp())
675 }
676}
677
678impl IntoRAs<f64> for &[f64] {
679 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
680 for (i, &val) in self.iter().enumerate() {
681 if !val.is_finite() {
682 return Err(StorageCoerceError::NonFinite {
683 to: "f64",
684 index: Some(i),
685 });
686 }
687 }
688 Ok(self.into_sexp())
689 }
690}
691
692impl IntoRAs<f64> for Vec<f32> {
694 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
695 let mut result = Vec::with_capacity(self.len());
696 for (i, val) in self.into_iter().enumerate() {
697 if !val.is_finite() {
698 return Err(StorageCoerceError::NonFinite {
699 to: "f64",
700 index: Some(i),
701 });
702 }
703 result.push(val as f64);
704 }
705 Ok(result.into_sexp())
706 }
707}
708
709impl IntoRAs<f64> for &[f32] {
710 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
711 let mut result = Vec::with_capacity(self.len());
712 for (i, &val) in self.iter().enumerate() {
713 if !val.is_finite() {
714 return Err(StorageCoerceError::NonFinite {
715 to: "f64",
716 index: Some(i),
717 });
718 }
719 result.push(val as f64);
720 }
721 Ok(result.into_sexp())
722 }
723}
724
725macro_rules! impl_vec_into_r_as_f64_infallible {
727 ($from:ty) => {
728 impl IntoRAs<f64> for Vec<$from> {
729 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
730 let result: Vec<f64> = self.into_iter().map(|v| v as f64).collect();
731 Ok(result.into_sexp())
732 }
733 }
734
735 impl IntoRAs<f64> for &[$from] {
736 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
737 let result: Vec<f64> = self.iter().map(|&v| v as f64).collect();
738 Ok(result.into_sexp())
739 }
740 }
741 };
742}
743
744impl_vec_into_r_as_f64_infallible!(i8);
745impl_vec_into_r_as_f64_infallible!(i16);
746impl_vec_into_r_as_f64_infallible!(u8);
747impl_vec_into_r_as_f64_infallible!(u16);
748impl_vec_into_r_as_f64_infallible!(u32);
749
750impl IntoRAs<f64> for Vec<i32> {
754 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
755 let mut result = Vec::with_capacity(self.len());
756 for (i, val) in self.into_iter().enumerate() {
757 if val == crate::altrep_traits::NA_INTEGER {
758 return Err(StorageCoerceError::MissingValue {
759 to: "f64",
760 index: Some(i),
761 });
762 }
763 result.push(val as f64);
764 }
765 Ok(result.into_sexp())
766 }
767}
768
769impl IntoRAs<f64> for &[i32] {
770 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
771 let mut result = Vec::with_capacity(self.len());
772 for (i, &val) in self.iter().enumerate() {
773 if val == crate::altrep_traits::NA_INTEGER {
774 return Err(StorageCoerceError::MissingValue {
775 to: "f64",
776 index: Some(i),
777 });
778 }
779 result.push(val as f64);
780 }
781 Ok(result.into_sexp())
782 }
783}
784
785impl_vec_into_r_as!(f64, "f64"; i64, "i64");
787impl_vec_into_r_as!(f64, "f64"; u64, "u64");
788impl_vec_into_r_as!(f64, "f64"; isize, "isize");
789impl_vec_into_r_as!(f64, "f64"; usize, "usize");
790
791impl IntoRAs<f64> for Vec<bool> {
793 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
794 let result: Vec<f64> = self
795 .into_iter()
796 .map(|b| if b { 1.0 } else { 0.0 })
797 .collect();
798 Ok(result.into_sexp())
799 }
800}
801
802impl IntoRAs<f64> for &[bool] {
803 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
804 let result: Vec<f64> = self.iter().map(|&b| if b { 1.0 } else { 0.0 }).collect();
805 Ok(result.into_sexp())
806 }
807}
808impl IntoRAs<u8> for Vec<u8> {
814 #[inline]
815 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
816 Ok(self.into_sexp())
817 }
818}
819
820impl IntoRAs<u8> for &[u8] {
821 #[inline]
822 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
823 Ok(self.into_sexp())
824 }
825}
826
827impl_vec_into_r_as!(u8, "u8"; i8, "i8");
828impl_vec_into_r_as!(u8, "u8"; i16, "i16");
829impl_vec_into_r_as!(u8, "u8"; i32, "i32");
830impl_vec_into_r_as!(u8, "u8"; i64, "i64");
831impl_vec_into_r_as!(u8, "u8"; isize, "isize");
832impl_vec_into_r_as!(u8, "u8"; u16, "u16");
833impl_vec_into_r_as!(u8, "u8"; u32, "u32");
834impl_vec_into_r_as!(u8, "u8"; u64, "u64");
835impl_vec_into_r_as!(u8, "u8"; usize, "usize");
836impl_vec_into_r_as!(u8, "u8"; f32, "f32");
837impl_vec_into_r_as!(u8, "u8"; f64, "f64");
838impl IntoRAs<RLogical> for Vec<bool> {
843 #[inline]
844 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
845 Ok(self.into_sexp())
846 }
847}
848
849impl IntoRAs<RLogical> for &[bool] {
850 #[inline]
851 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
852 Ok(self.into_sexp())
853 }
854}
855impl IntoRAs<String> for Vec<String> {
860 #[inline]
861 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
862 Ok(self.into_sexp())
863 }
864}
865
866impl IntoRAs<String> for &[String] {
867 #[inline]
868 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
869 Ok(self.into_sexp())
870 }
871}
872
873impl IntoRAs<String> for Vec<&str> {
874 #[inline]
875 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
876 Ok(self.into_sexp())
877 }
878}
879
880impl IntoRAs<String> for &[&str] {
881 #[inline]
882 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
883 Ok(self.into_sexp())
884 }
885}
886
887impl IntoRAs<String> for Vec<f64> {
889 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
890 let strings: Vec<String> = self
891 .into_iter()
892 .map(|v| {
893 if v.is_nan() {
894 "NaN".to_string()
895 } else if v.is_infinite() {
896 if v.is_sign_positive() {
897 "Inf".to_string()
898 } else {
899 "-Inf".to_string()
900 }
901 } else {
902 v.to_string()
903 }
904 })
905 .collect();
906 Ok(strings.into_sexp())
907 }
908}
909
910impl IntoRAs<String> for Vec<i32> {
911 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
912 let strings: Vec<String> = self.into_iter().map(|v| v.to_string()).collect();
913 Ok(strings.into_sexp())
914 }
915}
916
917impl IntoRAs<String> for Vec<i64> {
918 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
919 let strings: Vec<String> = self.into_iter().map(|v| v.to_string()).collect();
920 Ok(strings.into_sexp())
921 }
922}
923
924impl IntoRAs<String> for Vec<bool> {
925 fn into_r_as(self) -> Result<SEXP, StorageCoerceError> {
926 let strings: Vec<String> = self
927 .into_iter()
928 .map(|b| if b { "TRUE" } else { "FALSE" }.to_string())
929 .collect();
930 Ok(strings.into_sexp())
931 }
932}
933#[cfg(test)]
938mod tests {
939 use super::*;
940
941 fn _assert_into_r_as<T, Target>()
945 where
946 T: IntoRAs<Target>,
947 {
948 }
949
950 #[test]
951 fn test_trait_bounds() {
952 _assert_into_r_as::<i32, i32>();
954 _assert_into_r_as::<i64, i32>();
955 _assert_into_r_as::<f64, i32>();
956 _assert_into_r_as::<bool, i32>();
957
958 _assert_into_r_as::<f64, f64>();
960 _assert_into_r_as::<i32, f64>();
961 _assert_into_r_as::<i64, f64>();
962 _assert_into_r_as::<bool, f64>();
963
964 _assert_into_r_as::<u8, u8>();
966 _assert_into_r_as::<i32, u8>();
967
968 _assert_into_r_as::<bool, RLogical>();
970 _assert_into_r_as::<i32, RLogical>();
971
972 _assert_into_r_as::<String, String>();
974 _assert_into_r_as::<&str, String>();
975 _assert_into_r_as::<f64, String>();
976 _assert_into_r_as::<i32, String>();
977 _assert_into_r_as::<bool, String>();
978
979 _assert_into_r_as::<Vec<i32>, i32>();
981 _assert_into_r_as::<Vec<i64>, i32>();
982 _assert_into_r_as::<Vec<f64>, i32>();
983
984 _assert_into_r_as::<Vec<f64>, f64>();
986 _assert_into_r_as::<Vec<i32>, f64>();
987 _assert_into_r_as::<Vec<i64>, f64>();
988
989 _assert_into_r_as::<Vec<u8>, u8>();
991 _assert_into_r_as::<Vec<i32>, u8>();
992
993 _assert_into_r_as::<Vec<String>, String>();
995 _assert_into_r_as::<Vec<f64>, String>();
996 }
997}
998