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