1#![allow(rustdoc::private_intra_doc_links)]
2use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
39
40use crate::altrep_traits::NA_REAL;
41use crate::coerce::TryCoerce;
42use crate::ffi::{RLogical, SEXP, SEXPTYPE, SexpExt};
43
44#[inline]
50pub(crate) fn is_na_real(value: f64) -> bool {
51 value.to_bits() == NA_REAL.to_bits()
52}
53
54#[inline]
67pub(crate) unsafe fn charsxp_to_str(charsxp: SEXP) -> &'static str {
68 unsafe { charsxp_to_str_impl(charsxp.r_char(), charsxp) }
69}
70
71#[inline]
73pub(crate) unsafe fn charsxp_to_str_unchecked(charsxp: SEXP) -> &'static str {
74 unsafe { charsxp_to_str_impl(charsxp.r_char_unchecked(), charsxp) }
75}
76
77#[inline]
81unsafe fn charsxp_to_str_impl(ptr: *const std::os::raw::c_char, charsxp: SEXP) -> &'static str {
82 unsafe {
83 let len: usize = charsxp.len();
84 let bytes = r_slice(ptr.cast::<u8>(), len);
85 debug_assert!(
88 std::str::from_utf8(bytes).is_ok(),
89 "CHARSXP contains non-UTF-8 bytes (locale assertion may have been skipped)"
90 );
91 std::str::from_utf8_unchecked(bytes)
92 }
93}
94
95#[inline]
98pub(crate) unsafe fn charsxp_to_cow(charsxp: SEXP) -> std::borrow::Cow<'static, str> {
99 std::borrow::Cow::Borrowed(unsafe { charsxp_to_str(charsxp) })
100}
101
102#[inline(always)]
115pub(crate) unsafe fn r_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
116 if len == 0 {
117 &[]
118 } else {
119 unsafe { std::slice::from_raw_parts(ptr, len) }
120 }
121}
122
123#[inline(always)]
129pub(crate) unsafe fn r_slice_mut<'a, T>(ptr: *mut T, len: usize) -> &'a mut [T] {
130 if len == 0 {
131 &mut []
132 } else {
133 unsafe { std::slice::from_raw_parts_mut(ptr, len) }
134 }
135}
136
137#[derive(Debug, Clone, Copy)]
138pub struct SexpTypeError {
140 pub expected: SEXPTYPE,
142 pub actual: SEXPTYPE,
144}
145
146impl std::fmt::Display for SexpTypeError {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 write!(
149 f,
150 "type mismatch: expected {:?}, got {:?}",
151 self.expected, self.actual
152 )
153 }
154}
155
156impl std::error::Error for SexpTypeError {}
157
158#[derive(Debug, Clone, Copy)]
159pub struct SexpLengthError {
161 pub expected: usize,
163 pub actual: usize,
165}
166
167impl std::fmt::Display for SexpLengthError {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 write!(
170 f,
171 "length mismatch: expected {}, got {}",
172 self.expected, self.actual
173 )
174 }
175}
176
177impl std::error::Error for SexpLengthError {}
178
179#[derive(Debug, Clone, Copy)]
180pub struct SexpNaError {
182 pub sexp_type: SEXPTYPE,
184}
185
186impl std::fmt::Display for SexpNaError {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 write!(f, "unexpected NA value in {:?}", self.sexp_type)
189 }
190}
191
192impl std::error::Error for SexpNaError {}
193
194#[derive(Debug, Clone)]
195pub enum SexpError {
197 Type(SexpTypeError),
199 Length(SexpLengthError),
201 Na(SexpNaError),
203 InvalidValue(String),
205 MissingField(String),
207 DuplicateName(String),
209 #[cfg(feature = "either")]
213 EitherConversion {
214 left_error: String,
216 right_error: String,
218 },
219}
220
221impl std::fmt::Display for SexpError {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 match self {
224 SexpError::Type(e) => write!(f, "{}", e),
225 SexpError::Length(e) => write!(f, "{}", e),
226 SexpError::Na(e) => write!(f, "{}", e),
227 SexpError::InvalidValue(msg) => write!(f, "invalid value: {}", msg),
228 SexpError::MissingField(name) => write!(f, "missing field: {}", name),
229 SexpError::DuplicateName(name) => write!(f, "duplicate name in list: {:?}", name),
230 #[cfg(feature = "either")]
231 SexpError::EitherConversion {
232 left_error,
233 right_error,
234 } => write!(
235 f,
236 "failed to convert to Either: Left failed ({}), Right failed ({})",
237 left_error, right_error
238 ),
239 }
240 }
241}
242
243impl std::error::Error for SexpError {
244 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
245 match self {
246 SexpError::Type(e) => Some(e),
247 SexpError::Length(e) => Some(e),
248 SexpError::Na(e) => Some(e),
249 SexpError::InvalidValue(_) => None,
250 SexpError::MissingField(_) => None,
251 SexpError::DuplicateName(_) => None,
252 #[cfg(feature = "either")]
253 SexpError::EitherConversion { .. } => None,
254 }
255 }
256}
257
258impl From<SexpTypeError> for SexpError {
259 fn from(e: SexpTypeError) -> Self {
260 SexpError::Type(e)
261 }
262}
263
264impl From<SexpLengthError> for SexpError {
265 fn from(e: SexpLengthError) -> Self {
266 SexpError::Length(e)
267 }
268}
269
270impl From<SexpNaError> for SexpError {
271 fn from(e: SexpNaError) -> Self {
272 SexpError::Na(e)
273 }
274}
275
276pub trait TryFromSexp: Sized {
290 type Error;
292
293 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error>;
297
298 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
306 Self::try_from_sexp(sexp)
308 }
309}
310
311macro_rules! impl_try_from_sexp_scalar_native {
312 ($t:ty, $sexptype:ident) => {
313 impl TryFromSexp for $t {
314 type Error = SexpError;
315
316 #[inline]
317 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
318 let actual = sexp.type_of();
319 if actual != SEXPTYPE::$sexptype {
320 return Err(SexpTypeError {
321 expected: SEXPTYPE::$sexptype,
322 actual,
323 }
324 .into());
325 }
326 let len = sexp.len();
327 if len != 1 {
328 return Err(SexpLengthError {
329 expected: 1,
330 actual: len,
331 }
332 .into());
333 }
334 unsafe { sexp.as_slice::<$t>() }
335 .first()
336 .cloned()
337 .ok_or_else(|| {
338 SexpLengthError {
339 expected: 1,
340 actual: 0,
341 }
342 .into()
343 })
344 }
345
346 #[inline]
347 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
348 let actual = sexp.type_of();
349 if actual != SEXPTYPE::$sexptype {
350 return Err(SexpTypeError {
351 expected: SEXPTYPE::$sexptype,
352 actual,
353 }
354 .into());
355 }
356 let len = unsafe { sexp.len_unchecked() };
357 if len != 1 {
358 return Err(SexpLengthError {
359 expected: 1,
360 actual: len,
361 }
362 .into());
363 }
364 unsafe { sexp.as_slice_unchecked::<$t>() }
365 .first()
366 .cloned()
367 .ok_or_else(|| {
368 SexpLengthError {
369 expected: 1,
370 actual: 0,
371 }
372 .into()
373 })
374 }
375 }
376 };
377}
378
379impl_try_from_sexp_scalar_native!(i32, INTSXP);
380impl_try_from_sexp_scalar_native!(f64, REALSXP);
381impl_try_from_sexp_scalar_native!(u8, RAWSXP);
382impl_try_from_sexp_scalar_native!(RLogical, LGLSXP);
383impl_try_from_sexp_scalar_native!(crate::ffi::Rcomplex, CPLXSXP);
384
385impl TryFromSexp for SEXP {
412 type Error = SexpError;
413
414 #[inline]
421 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
422 Ok(unsafe { crate::altrep_sexp::ensure_materialized(sexp) })
423 }
424
425 #[inline]
426 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
427 Ok(unsafe { crate::altrep_sexp::ensure_materialized(sexp) })
428 }
429}
430
431impl TryFromSexp for Option<SEXP> {
432 type Error = SexpError;
433
434 #[inline]
435 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
436 if sexp.type_of() == SEXPTYPE::NILSXP {
437 Ok(None)
438 } else {
439 Ok(Some(unsafe {
440 crate::altrep_sexp::ensure_materialized(sexp)
441 }))
442 }
443 }
444
445 #[inline]
446 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
447 Self::try_from_sexp(sexp)
448 }
449}
450mod logical;
453
454mod coerced_scalars;
455pub(crate) use coerced_scalars::coerce_value;
456
457mod references;
458
459impl<T> TryFromSexp for &[T]
467where
468 T: crate::ffi::RNativeType + Copy,
469{
470 type Error = SexpTypeError;
471
472 #[inline]
473 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
474 let actual = sexp.type_of();
475 if actual != T::SEXP_TYPE {
476 return Err(SexpTypeError {
477 expected: T::SEXP_TYPE,
478 actual,
479 });
480 }
481 Ok(unsafe { sexp.as_slice::<T>() })
482 }
483
484 #[inline]
485 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
486 let actual = sexp.type_of();
487 if actual != T::SEXP_TYPE {
488 return Err(SexpTypeError {
489 expected: T::SEXP_TYPE,
490 actual,
491 });
492 }
493 Ok(unsafe { sexp.as_slice_unchecked::<T>() })
494 }
495}
496
497impl<T> TryFromSexp for &mut [T]
505where
506 T: crate::ffi::RNativeType + Copy,
507{
508 type Error = SexpTypeError;
509
510 #[inline]
511 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
512 let actual = sexp.type_of();
513 if actual != T::SEXP_TYPE {
514 return Err(SexpTypeError {
515 expected: T::SEXP_TYPE,
516 actual,
517 });
518 }
519 let len = sexp.len();
520 let ptr = unsafe { T::dataptr_mut(sexp) };
521 Ok(unsafe { r_slice_mut(ptr, len) })
522 }
523
524 #[inline]
525 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
526 let actual = sexp.type_of();
527 if actual != T::SEXP_TYPE {
528 return Err(SexpTypeError {
529 expected: T::SEXP_TYPE,
530 actual,
531 });
532 }
533 let len = unsafe { sexp.len_unchecked() };
534 let ptr = unsafe { T::dataptr_mut(sexp) };
535 Ok(unsafe { r_slice_mut(ptr, len) })
536 }
537}
538
539impl<T> TryFromSexp for Option<&[T]>
541where
542 T: crate::ffi::RNativeType + Copy,
543{
544 type Error = SexpError;
545
546 #[inline]
547 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
548 if sexp.type_of() == SEXPTYPE::NILSXP {
549 return Ok(None);
550 }
551 let slice: &[T] = TryFromSexp::try_from_sexp(sexp).map_err(SexpError::from)?;
552 Ok(Some(slice))
553 }
554
555 #[inline]
556 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
557 if sexp.type_of() == SEXPTYPE::NILSXP {
558 return Ok(None);
559 }
560 let slice: &[T] =
561 unsafe { TryFromSexp::try_from_sexp_unchecked(sexp).map_err(SexpError::from)? };
562 Ok(Some(slice))
563 }
564}
565
566impl<T> TryFromSexp for Option<&mut [T]>
568where
569 T: crate::ffi::RNativeType + Copy,
570{
571 type Error = SexpError;
572
573 #[inline]
574 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
575 if sexp.type_of() == SEXPTYPE::NILSXP {
576 return Ok(None);
577 }
578 let slice: &mut [T] = TryFromSexp::try_from_sexp(sexp).map_err(SexpError::from)?;
579 Ok(Some(slice))
580 }
581
582 #[inline]
583 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
584 if sexp.type_of() == SEXPTYPE::NILSXP {
585 return Ok(None);
586 }
587 let slice: &mut [T] =
588 unsafe { TryFromSexp::try_from_sexp_unchecked(sexp).map_err(SexpError::from)? };
589 Ok(Some(slice))
590 }
591}
592mod strings;
595
596impl<T> TryFromSexp for Result<T, ()>
599where
600 T: TryFromSexp,
601 T::Error: Into<SexpError>,
602{
603 type Error = SexpError;
604
605 #[inline]
606 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
607 if sexp.type_of() == SEXPTYPE::NILSXP {
608 return Ok(Err(()));
609 }
610 let value = T::try_from_sexp(sexp).map_err(Into::into)?;
611 Ok(Ok(value))
612 }
613
614 #[inline]
615 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
616 if sexp.type_of() == SEXPTYPE::NILSXP {
617 return Ok(Err(()));
618 }
619 let value = unsafe { T::try_from_sexp_unchecked(sexp).map_err(Into::into)? };
620 Ok(Ok(value))
621 }
622}
623mod na_vectors;
626
627mod collections;
628
629impl<T, const N: usize> TryFromSexp for [T; N]
636where
637 T: crate::ffi::RNativeType + Copy,
638{
639 type Error = SexpError;
640
641 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
642 let slice: &[T] = TryFromSexp::try_from_sexp(sexp)?;
643 if slice.len() != N {
644 return Err(SexpLengthError {
645 expected: N,
646 actual: slice.len(),
647 }
648 .into());
649 }
650
651 let mut arr = std::mem::MaybeUninit::<[T; N]>::uninit();
653 unsafe {
654 let dst: &mut [T] = std::slice::from_raw_parts_mut(arr.as_mut_ptr().cast::<T>(), N);
657 dst.copy_from_slice(&slice[..N]);
658 Ok(arr.assume_init())
659 }
660 }
661
662 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
663 Self::try_from_sexp(sexp)
664 }
665}
666use std::collections::VecDeque;
671
672impl<T> TryFromSexp for VecDeque<T>
674where
675 T: crate::ffi::RNativeType + Copy,
676{
677 type Error = SexpTypeError;
678
679 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
680 let slice: &[T] = TryFromSexp::try_from_sexp(sexp)?;
681 Ok(VecDeque::from(slice.to_vec()))
682 }
683
684 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
685 let slice: &[T] = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
686 Ok(VecDeque::from(slice.to_vec()))
687 }
688}
689use std::collections::BinaryHeap;
694
695impl<T> TryFromSexp for BinaryHeap<T>
699where
700 T: crate::ffi::RNativeType + Copy + Ord,
701{
702 type Error = SexpTypeError;
703
704 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
705 let slice: &[T] = TryFromSexp::try_from_sexp(sexp)?;
706 Ok(BinaryHeap::from(slice.to_vec()))
707 }
708
709 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
710 let slice: &[T] = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
711 Ok(BinaryHeap::from(slice.to_vec()))
712 }
713}
714mod cow_and_paths;
717
718impl<T> TryFromSexp for Option<Vec<T>>
725where
726 Vec<T>: TryFromSexp,
727 <Vec<T> as TryFromSexp>::Error: Into<SexpError>,
728{
729 type Error = SexpError;
730
731 #[inline]
732 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
733 if sexp.type_of() == SEXPTYPE::NILSXP {
734 Ok(None)
735 } else {
736 Vec::<T>::try_from_sexp(sexp).map(Some).map_err(Into::into)
737 }
738 }
739
740 #[inline]
741 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
742 if sexp.type_of() == SEXPTYPE::NILSXP {
743 Ok(None)
744 } else {
745 unsafe {
746 Vec::<T>::try_from_sexp_unchecked(sexp)
747 .map(Some)
748 .map_err(Into::into)
749 }
750 }
751 }
752}
753
754macro_rules! impl_option_map_try_from_sexp {
755 ($(#[$meta:meta])* $map_ty:ident) => {
756 $(#[$meta])*
757 impl<V: TryFromSexp> TryFromSexp for Option<$map_ty<String, V>>
758 where
759 V::Error: Into<SexpError>,
760 {
761 type Error = SexpError;
762
763 #[inline]
764 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
765 if sexp.type_of() == SEXPTYPE::NILSXP {
766 Ok(None)
767 } else {
768 $map_ty::<String, V>::try_from_sexp(sexp).map(Some)
769 }
770 }
771 }
772 };
773}
774
775impl_option_map_try_from_sexp!(
776 HashMap
778);
779impl_option_map_try_from_sexp!(
780 BTreeMap
782);
783
784macro_rules! impl_option_set_try_from_sexp {
785 ($(#[$meta:meta])* $set_ty:ident) => {
786 $(#[$meta])*
787 impl<T> TryFromSexp for Option<$set_ty<T>>
788 where
789 $set_ty<T>: TryFromSexp,
790 <$set_ty<T> as TryFromSexp>::Error: Into<SexpError>,
791 {
792 type Error = SexpError;
793
794 #[inline]
795 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
796 if sexp.type_of() == SEXPTYPE::NILSXP {
797 Ok(None)
798 } else {
799 $set_ty::<T>::try_from_sexp(sexp)
800 .map(Some)
801 .map_err(Into::into)
802 }
803 }
804 }
805 };
806}
807
808impl_option_set_try_from_sexp!(
809 HashSet
811);
812impl_option_set_try_from_sexp!(
813 BTreeSet
815);
816impl<T> TryFromSexp for Vec<Vec<T>>
824where
825 Vec<T>: TryFromSexp,
826 <Vec<T> as TryFromSexp>::Error: Into<SexpError>,
827{
828 type Error = SexpError;
829
830 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
831 let actual = sexp.type_of();
832 if actual != SEXPTYPE::VECSXP {
833 return Err(SexpTypeError {
834 expected: SEXPTYPE::VECSXP,
835 actual,
836 }
837 .into());
838 }
839
840 let len = sexp.len();
841 let mut result = Vec::with_capacity(len);
842
843 for i in 0..len {
844 let elem = sexp.vector_elt(i as crate::ffi::R_xlen_t);
845 let inner: Vec<T> = Vec::<T>::try_from_sexp(elem).map_err(Into::into)?;
846 result.push(inner);
847 }
848
849 Ok(result)
850 }
851
852 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
853 let actual = sexp.type_of();
854 if actual != SEXPTYPE::VECSXP {
855 return Err(SexpTypeError {
856 expected: SEXPTYPE::VECSXP,
857 actual,
858 }
859 .into());
860 }
861
862 let len = sexp.len();
863 let mut result = Vec::with_capacity(len);
864
865 for i in 0..len {
866 let elem = sexp.vector_elt(i as crate::ffi::R_xlen_t);
867 let inner: Vec<T> =
868 unsafe { Vec::<T>::try_from_sexp_unchecked(elem).map_err(Into::into)? };
869 result.push(inner);
870 }
871
872 Ok(result)
873 }
874}
875use crate::coerce::Coerced;
880
881impl<T, R> TryFromSexp for Coerced<T, R>
895where
896 R: TryFromSexp,
897 R: TryCoerce<T>,
898 <R as TryFromSexp>::Error: Into<SexpError>,
899 <R as TryCoerce<T>>::Error: std::fmt::Debug,
900{
901 type Error = SexpError;
902
903 #[inline]
904 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
905 let r_val: R = R::try_from_sexp(sexp).map_err(Into::into)?;
906 let value: T = r_val
907 .try_coerce()
908 .map_err(|e| SexpError::InvalidValue(format!("{e:?}")))?;
909 Ok(Coerced::new(value))
910 }
911
912 #[inline]
913 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
914 let r_val: R = unsafe { R::try_from_sexp_unchecked(sexp).map_err(Into::into)? };
915 let value: T = r_val
916 .try_coerce()
917 .map_err(|e| SexpError::InvalidValue(format!("{e:?}")))?;
918 Ok(Coerced::new(value))
919 }
920}
921#[inline]
931fn coerce_slice_to_vec<R, T>(slice: &[R]) -> Result<Vec<T>, SexpError>
932where
933 R: Copy + TryCoerce<T>,
934 <R as TryCoerce<T>>::Error: std::fmt::Debug,
935{
936 slice
937 .iter()
938 .copied()
939 .map(|v| {
940 v.try_coerce()
941 .map_err(|e| SexpError::InvalidValue(format!("{e:?}")))
942 })
943 .collect()
944}
945
946#[inline]
948fn try_from_sexp_numeric_vec<T>(sexp: SEXP) -> Result<Vec<T>, SexpError>
949where
950 i32: TryCoerce<T>,
951 f64: TryCoerce<T>,
952 u8: TryCoerce<T>,
953 <i32 as TryCoerce<T>>::Error: std::fmt::Debug,
954 <f64 as TryCoerce<T>>::Error: std::fmt::Debug,
955 <u8 as TryCoerce<T>>::Error: std::fmt::Debug,
956{
957 let actual = sexp.type_of();
958 match actual {
959 SEXPTYPE::INTSXP => {
960 let slice: &[i32] = unsafe { sexp.as_slice() };
961 coerce_slice_to_vec(slice)
962 }
963 SEXPTYPE::REALSXP => {
964 let slice: &[f64] = unsafe { sexp.as_slice() };
965 coerce_slice_to_vec(slice)
966 }
967 SEXPTYPE::RAWSXP => {
968 let slice: &[u8] = unsafe { sexp.as_slice() };
969 coerce_slice_to_vec(slice)
970 }
971 SEXPTYPE::LGLSXP => {
972 let slice: &[RLogical] = unsafe { sexp.as_slice() };
973 slice.iter().map(|v| coerce_value(v.to_i32())).collect()
974 }
975 _ => Err(SexpError::InvalidValue(format!(
976 "expected integer, numeric, logical, or raw; got {:?}",
977 actual
978 ))),
979 }
980}
981
982macro_rules! impl_vec_try_from_sexp_numeric {
984 ($target:ty) => {
985 impl TryFromSexp for Vec<$target> {
986 type Error = SexpError;
987
988 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
989 try_from_sexp_numeric_vec(sexp)
990 }
991
992 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
993 try_from_sexp_numeric_vec(sexp)
994 }
995 }
996 };
997}
998
999impl_vec_try_from_sexp_numeric!(i8);
1000impl_vec_try_from_sexp_numeric!(i16);
1001impl_vec_try_from_sexp_numeric!(i64);
1002impl_vec_try_from_sexp_numeric!(isize);
1003impl_vec_try_from_sexp_numeric!(u16);
1004impl_vec_try_from_sexp_numeric!(u32);
1005impl_vec_try_from_sexp_numeric!(u64);
1006impl_vec_try_from_sexp_numeric!(usize);
1007impl_vec_try_from_sexp_numeric!(f32);
1008
1009impl TryFromSexp for Vec<bool> {
1011 type Error = SexpError;
1012
1013 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1014 let actual = sexp.type_of();
1015 if actual != SEXPTYPE::LGLSXP {
1016 return Err(SexpTypeError {
1017 expected: SEXPTYPE::LGLSXP,
1018 actual,
1019 }
1020 .into());
1021 }
1022 let slice: &[RLogical] = unsafe { sexp.as_slice() };
1023 coerce_slice_to_vec(slice)
1024 }
1025
1026 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
1027 Self::try_from_sexp(sexp)
1028 }
1029}
1030
1031impl TryFromSexp for Box<[bool]> {
1032 type Error = SexpError;
1033
1034 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1035 let vec: Vec<bool> = TryFromSexp::try_from_sexp(sexp)?;
1036 Ok(vec.into_boxed_slice())
1037 }
1038}
1039#[inline]
1045fn try_from_sexp_numeric_set<T, S>(sexp: SEXP) -> Result<S, SexpError>
1046where
1047 S: std::iter::FromIterator<T>,
1048 i32: TryCoerce<T>,
1049 f64: TryCoerce<T>,
1050 u8: TryCoerce<T>,
1051 <i32 as TryCoerce<T>>::Error: std::fmt::Debug,
1052 <f64 as TryCoerce<T>>::Error: std::fmt::Debug,
1053 <u8 as TryCoerce<T>>::Error: std::fmt::Debug,
1054{
1055 let vec = try_from_sexp_numeric_vec(sexp)?;
1056 Ok(vec.into_iter().collect())
1057}
1058
1059macro_rules! impl_set_try_from_sexp_numeric {
1060 ($set_ty:ident, $target:ty) => {
1061 impl TryFromSexp for $set_ty<$target> {
1062 type Error = SexpError;
1063
1064 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1065 try_from_sexp_numeric_set(sexp)
1066 }
1067
1068 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
1069 try_from_sexp_numeric_set(sexp)
1070 }
1071 }
1072 };
1073}
1074
1075impl_set_try_from_sexp_numeric!(HashSet, i8);
1076impl_set_try_from_sexp_numeric!(HashSet, i16);
1077impl_set_try_from_sexp_numeric!(HashSet, i64);
1078impl_set_try_from_sexp_numeric!(HashSet, isize);
1079impl_set_try_from_sexp_numeric!(HashSet, u16);
1080impl_set_try_from_sexp_numeric!(HashSet, u32);
1081impl_set_try_from_sexp_numeric!(HashSet, u64);
1082impl_set_try_from_sexp_numeric!(HashSet, usize);
1083
1084impl_set_try_from_sexp_numeric!(BTreeSet, i8);
1085impl_set_try_from_sexp_numeric!(BTreeSet, i16);
1086impl_set_try_from_sexp_numeric!(BTreeSet, i64);
1087impl_set_try_from_sexp_numeric!(BTreeSet, isize);
1088impl_set_try_from_sexp_numeric!(BTreeSet, u16);
1089impl_set_try_from_sexp_numeric!(BTreeSet, u32);
1090impl_set_try_from_sexp_numeric!(BTreeSet, u64);
1091impl_set_try_from_sexp_numeric!(BTreeSet, usize);
1092
1093macro_rules! impl_set_try_from_sexp_bool {
1094 ($set_ty:ident) => {
1095 impl TryFromSexp for $set_ty<bool> {
1096 type Error = SexpError;
1097
1098 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1099 let vec: Vec<bool> = TryFromSexp::try_from_sexp(sexp)?;
1100 Ok(vec.into_iter().collect())
1101 }
1102
1103 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
1104 Self::try_from_sexp(sexp)
1105 }
1106 }
1107 };
1108}
1109
1110impl_set_try_from_sexp_bool!(HashSet);
1111impl_set_try_from_sexp_bool!(BTreeSet);
1112use crate::externalptr::{ExternalPtr, TypeMismatchError, TypedExternal};
1117
1118impl<T: TypedExternal + Send> TryFromSexp for ExternalPtr<T> {
1134 type Error = SexpError;
1135
1136 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1137 let actual = sexp.type_of();
1138 if actual != SEXPTYPE::EXTPTRSXP {
1139 return Err(SexpTypeError {
1140 expected: SEXPTYPE::EXTPTRSXP,
1141 actual,
1142 }
1143 .into());
1144 }
1145
1146 unsafe { ExternalPtr::wrap_sexp_with_error(sexp) }.map_err(|e| match e {
1148 TypeMismatchError::NullPointer => {
1149 SexpError::InvalidValue("external pointer is null".to_string())
1150 }
1151 TypeMismatchError::InvalidTypeId => {
1152 SexpError::InvalidValue("external pointer has no valid type id".to_string())
1153 }
1154 TypeMismatchError::Mismatch { expected, found } => SexpError::InvalidValue(format!(
1155 "type mismatch: expected `{}`, found `{}`",
1156 expected, found
1157 )),
1158 })
1159 }
1160
1161 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
1162 let actual = sexp.type_of();
1163 if actual != SEXPTYPE::EXTPTRSXP {
1164 return Err(SexpTypeError {
1165 expected: SEXPTYPE::EXTPTRSXP,
1166 actual,
1167 }
1168 .into());
1169 }
1170
1171 unsafe { ExternalPtr::wrap_sexp_unchecked(sexp) }.ok_or_else(|| {
1173 SexpError::InvalidValue(
1174 "failed to convert external pointer: type mismatch or null pointer".to_string(),
1175 )
1176 })
1177 }
1178}
1179
1180impl<T: TypedExternal + Send> TryFromSexp for Option<ExternalPtr<T>> {
1181 type Error = SexpError;
1182
1183 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1184 if sexp.type_of() == SEXPTYPE::NILSXP {
1185 return Ok(None);
1186 }
1187 let ptr: ExternalPtr<T> = TryFromSexp::try_from_sexp(sexp)?;
1188 Ok(Some(ptr))
1189 }
1190
1191 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
1192 if sexp.type_of() == SEXPTYPE::NILSXP {
1193 return Ok(None);
1194 }
1195 let ptr: ExternalPtr<T> = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
1196 Ok(Some(ptr))
1197 }
1198}
1199#[macro_export]
1207macro_rules! impl_option_try_from_sexp {
1208 ($t:ty) => {
1209 impl $crate::from_r::TryFromSexp for Option<$t> {
1210 type Error = $crate::from_r::SexpError;
1211
1212 fn try_from_sexp(sexp: $crate::ffi::SEXP) -> Result<Self, Self::Error> {
1213 use $crate::ffi::{SEXPTYPE, SexpExt};
1214 if sexp.type_of() == SEXPTYPE::NILSXP {
1215 return Ok(None);
1216 }
1217 <$t as $crate::from_r::TryFromSexp>::try_from_sexp(sexp).map(Some)
1218 }
1219
1220 unsafe fn try_from_sexp_unchecked(
1221 sexp: $crate::ffi::SEXP,
1222 ) -> Result<Self, Self::Error> {
1223 use $crate::ffi::{SEXPTYPE, SexpExt};
1224 if sexp.type_of() == SEXPTYPE::NILSXP {
1225 return Ok(None);
1226 }
1227 unsafe {
1228 <$t as $crate::from_r::TryFromSexp>::try_from_sexp_unchecked(sexp).map(Some)
1229 }
1230 }
1231 }
1232 };
1233}
1234
1235#[macro_export]
1239macro_rules! impl_vec_try_from_sexp_list {
1240 ($t:ty) => {
1241 impl $crate::from_r::TryFromSexp for Vec<$t> {
1242 type Error = $crate::from_r::SexpError;
1243
1244 fn try_from_sexp(sexp: $crate::ffi::SEXP) -> Result<Self, Self::Error> {
1245 use $crate::ffi::{SEXPTYPE, SexpExt};
1246 use $crate::from_r::SexpTypeError;
1247
1248 let actual = sexp.type_of();
1249 if actual != SEXPTYPE::VECSXP {
1250 return Err(SexpTypeError {
1251 expected: SEXPTYPE::VECSXP,
1252 actual,
1253 }
1254 .into());
1255 }
1256
1257 let len = sexp.len();
1258 let mut result = Vec::with_capacity(len);
1259 for i in 0..len {
1260 let elem = sexp.vector_elt(i as $crate::ffi::R_xlen_t);
1261 result.push(<$t as $crate::from_r::TryFromSexp>::try_from_sexp(elem)?);
1262 }
1263 Ok(result)
1264 }
1265
1266 unsafe fn try_from_sexp_unchecked(
1267 sexp: $crate::ffi::SEXP,
1268 ) -> Result<Self, Self::Error> {
1269 use $crate::ffi::{SEXPTYPE, SexpExt};
1270 use $crate::from_r::SexpTypeError;
1271
1272 let actual = sexp.type_of();
1273 if actual != SEXPTYPE::VECSXP {
1274 return Err(SexpTypeError {
1275 expected: SEXPTYPE::VECSXP,
1276 actual,
1277 }
1278 .into());
1279 }
1280
1281 let len = unsafe { sexp.len_unchecked() };
1282 let mut result = Vec::with_capacity(len);
1283 for i in 0..len {
1284 let elem = unsafe { sexp.vector_elt_unchecked(i as $crate::ffi::R_xlen_t) };
1285 result.push(unsafe {
1286 <$t as $crate::from_r::TryFromSexp>::try_from_sexp_unchecked(elem)?
1287 });
1288 }
1289 Ok(result)
1290 }
1291 }
1292 };
1293}
1294
1295#[macro_export]
1299macro_rules! impl_vec_option_try_from_sexp_list {
1300 ($t:ty) => {
1301 impl $crate::from_r::TryFromSexp for Vec<Option<$t>> {
1302 type Error = $crate::from_r::SexpError;
1303
1304 fn try_from_sexp(sexp: $crate::ffi::SEXP) -> Result<Self, Self::Error> {
1305 use $crate::ffi::{SEXPTYPE, SexpExt};
1306 use $crate::from_r::SexpTypeError;
1307
1308 let actual = sexp.type_of();
1309 if actual != SEXPTYPE::VECSXP {
1310 return Err(SexpTypeError {
1311 expected: SEXPTYPE::VECSXP,
1312 actual,
1313 }
1314 .into());
1315 }
1316
1317 let len = sexp.len();
1318 let mut result = Vec::with_capacity(len);
1319 for i in 0..len {
1320 let elem = sexp.vector_elt(i as $crate::ffi::R_xlen_t);
1321 if elem == $crate::ffi::SEXP::nil() {
1322 result.push(None);
1323 } else {
1324 result.push(Some(<$t as $crate::from_r::TryFromSexp>::try_from_sexp(
1325 elem,
1326 )?));
1327 }
1328 }
1329 Ok(result)
1330 }
1331
1332 unsafe fn try_from_sexp_unchecked(
1333 sexp: $crate::ffi::SEXP,
1334 ) -> Result<Self, Self::Error> {
1335 use $crate::ffi::{SEXPTYPE, SexpExt};
1336 use $crate::from_r::SexpTypeError;
1337
1338 let actual = sexp.type_of();
1339 if actual != SEXPTYPE::VECSXP {
1340 return Err(SexpTypeError {
1341 expected: SEXPTYPE::VECSXP,
1342 actual,
1343 }
1344 .into());
1345 }
1346
1347 let len = unsafe { sexp.len_unchecked() };
1348 let mut result = Vec::with_capacity(len);
1349 for i in 0..len {
1350 let elem = unsafe { sexp.vector_elt_unchecked(i as $crate::ffi::R_xlen_t) };
1351 if elem == $crate::ffi::SEXP::nil() {
1352 result.push(None);
1353 } else {
1354 result.push(Some(unsafe {
1355 <$t as $crate::from_r::TryFromSexp>::try_from_sexp_unchecked(elem)?
1356 }));
1357 }
1358 }
1359 Ok(result)
1360 }
1361 }
1362 };
1363}
1364