1use crate::altrep_traits::NA_INTEGER;
10use crate::coerce::TryCoerce;
11use crate::ffi::{RLogical, SEXP, SEXPTYPE, SexpExt};
12use crate::from_r::{SexpError, TryFromSexp, is_na_real};
13
14#[inline]
15pub(crate) fn coerce_value<R, T>(value: R) -> Result<T, SexpError>
16where
17 R: TryCoerce<T>,
18 <R as TryCoerce<T>>::Error: std::fmt::Debug,
19{
20 value
21 .try_coerce()
22 .map_err(|e| SexpError::InvalidValue(format!("{e:?}")))
23}
24
25#[inline]
26fn try_from_sexp_numeric_scalar<T>(sexp: SEXP) -> Result<T, SexpError>
27where
28 i32: TryCoerce<T>,
29 f64: TryCoerce<T>,
30 u8: TryCoerce<T>,
31 <i32 as TryCoerce<T>>::Error: std::fmt::Debug,
32 <f64 as TryCoerce<T>>::Error: std::fmt::Debug,
33 <u8 as TryCoerce<T>>::Error: std::fmt::Debug,
34{
35 let actual = sexp.type_of();
36 match actual {
37 SEXPTYPE::INTSXP => {
38 let value: i32 = TryFromSexp::try_from_sexp(sexp)?;
39 coerce_value(value)
40 }
41 SEXPTYPE::REALSXP => {
42 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
43 coerce_value(value)
44 }
45 SEXPTYPE::RAWSXP => {
46 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
47 coerce_value(value)
48 }
49 SEXPTYPE::LGLSXP => {
50 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
51 coerce_value(value.to_i32())
52 }
53 _ => Err(SexpError::InvalidValue(format!(
54 "expected integer, numeric, logical, or raw; got {:?}",
55 actual
56 ))),
57 }
58}
59
60#[inline]
61unsafe fn try_from_sexp_numeric_scalar_unchecked<T>(sexp: SEXP) -> Result<T, SexpError>
62where
63 i32: TryCoerce<T>,
64 f64: TryCoerce<T>,
65 u8: TryCoerce<T>,
66 <i32 as TryCoerce<T>>::Error: std::fmt::Debug,
67 <f64 as TryCoerce<T>>::Error: std::fmt::Debug,
68 <u8 as TryCoerce<T>>::Error: std::fmt::Debug,
69{
70 let actual = sexp.type_of();
71 match actual {
72 SEXPTYPE::INTSXP => {
73 let value: i32 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
74 coerce_value(value)
75 }
76 SEXPTYPE::REALSXP => {
77 let value: f64 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
78 coerce_value(value)
79 }
80 SEXPTYPE::RAWSXP => {
81 let value: u8 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
82 coerce_value(value)
83 }
84 SEXPTYPE::LGLSXP => {
85 let value: RLogical = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
86 coerce_value(value.to_i32())
87 }
88 _ => Err(SexpError::InvalidValue(format!(
89 "expected integer, numeric, logical, or raw; got {:?}",
90 actual
91 ))),
92 }
93}
94
95#[inline]
96fn try_from_sexp_numeric_option<T>(sexp: SEXP) -> Result<Option<T>, SexpError>
97where
98 i32: TryCoerce<T>,
99 f64: TryCoerce<T>,
100 u8: TryCoerce<T>,
101 <i32 as TryCoerce<T>>::Error: std::fmt::Debug,
102 <f64 as TryCoerce<T>>::Error: std::fmt::Debug,
103 <u8 as TryCoerce<T>>::Error: std::fmt::Debug,
104{
105 if sexp.type_of() == SEXPTYPE::NILSXP {
106 return Ok(None);
107 }
108
109 let actual = sexp.type_of();
110 match actual {
111 SEXPTYPE::INTSXP => {
112 let len = sexp.len();
114 if len != 1 {
115 return Err(crate::from_r::SexpLengthError {
116 expected: 1,
117 actual: len,
118 }
119 .into());
120 }
121 let value = unsafe { sexp.as_slice::<i32>() }
122 .first()
123 .cloned()
124 .ok_or_else(|| {
125 SexpError::from(crate::from_r::SexpLengthError {
126 expected: 1,
127 actual: 0,
128 })
129 })?;
130 if value == NA_INTEGER {
131 Ok(None)
132 } else {
133 coerce_value(value).map(Some)
134 }
135 }
136 SEXPTYPE::REALSXP => {
137 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
138 if is_na_real(value) {
139 Ok(None)
140 } else {
141 coerce_value(value).map(Some)
142 }
143 }
144 SEXPTYPE::RAWSXP => {
145 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
146 coerce_value(value).map(Some)
147 }
148 SEXPTYPE::LGLSXP => {
149 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
150 if value.is_na() {
151 Ok(None)
152 } else {
153 coerce_value(value.to_i32()).map(Some)
154 }
155 }
156 _ => Err(SexpError::InvalidValue(format!(
157 "expected integer, numeric, logical, or raw; got {:?}",
158 actual
159 ))),
160 }
161}
162
163#[inline]
164unsafe fn try_from_sexp_numeric_option_unchecked<T>(sexp: SEXP) -> Result<Option<T>, SexpError>
165where
166 i32: TryCoerce<T>,
167 f64: TryCoerce<T>,
168 u8: TryCoerce<T>,
169 <i32 as TryCoerce<T>>::Error: std::fmt::Debug,
170 <f64 as TryCoerce<T>>::Error: std::fmt::Debug,
171 <u8 as TryCoerce<T>>::Error: std::fmt::Debug,
172{
173 if sexp.type_of() == SEXPTYPE::NILSXP {
174 return Ok(None);
175 }
176
177 let actual = sexp.type_of();
178 match actual {
179 SEXPTYPE::INTSXP => {
180 let len = unsafe { sexp.len_unchecked() };
182 if len != 1 {
183 return Err(crate::from_r::SexpLengthError {
184 expected: 1,
185 actual: len,
186 }
187 .into());
188 }
189 let value = unsafe { sexp.as_slice_unchecked::<i32>() }
190 .first()
191 .cloned()
192 .ok_or_else(|| {
193 SexpError::from(crate::from_r::SexpLengthError {
194 expected: 1,
195 actual: 0,
196 })
197 })?;
198 if value == NA_INTEGER {
199 Ok(None)
200 } else {
201 coerce_value(value).map(Some)
202 }
203 }
204 SEXPTYPE::REALSXP => {
205 let value: f64 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
206 if is_na_real(value) {
207 Ok(None)
208 } else {
209 coerce_value(value).map(Some)
210 }
211 }
212 SEXPTYPE::RAWSXP => {
213 let value: u8 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
214 coerce_value(value).map(Some)
215 }
216 SEXPTYPE::LGLSXP => {
217 let value: RLogical = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
218 if value.is_na() {
219 Ok(None)
220 } else {
221 coerce_value(value.to_i32()).map(Some)
222 }
223 }
224 _ => Err(SexpError::InvalidValue(format!(
225 "expected integer, numeric, logical, or raw; got {:?}",
226 actual
227 ))),
228 }
229}
230
231impl TryFromSexp for i8 {
232 type Error = SexpError;
233
234 #[inline]
235 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
236 try_from_sexp_numeric_scalar(sexp)
237 }
238
239 #[inline]
240 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
241 unsafe { try_from_sexp_numeric_scalar_unchecked(sexp) }
242 }
243}
244
245impl TryFromSexp for i16 {
246 type Error = SexpError;
247
248 #[inline]
249 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
250 try_from_sexp_numeric_scalar(sexp)
251 }
252
253 #[inline]
254 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
255 unsafe { try_from_sexp_numeric_scalar_unchecked(sexp) }
256 }
257}
258
259impl TryFromSexp for u16 {
260 type Error = SexpError;
261
262 #[inline]
263 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
264 try_from_sexp_numeric_scalar(sexp)
265 }
266
267 #[inline]
268 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
269 unsafe { try_from_sexp_numeric_scalar_unchecked(sexp) }
270 }
271}
272
273impl TryFromSexp for u32 {
274 type Error = SexpError;
275
276 #[inline]
277 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
278 try_from_sexp_numeric_scalar(sexp)
279 }
280
281 #[inline]
282 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
283 unsafe { try_from_sexp_numeric_scalar_unchecked(sexp) }
284 }
285}
286
287impl TryFromSexp for f32 {
288 type Error = SexpError;
289
290 #[inline]
291 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
292 let actual = sexp.type_of();
293 match actual {
294 SEXPTYPE::INTSXP => {
295 let value: i32 = TryFromSexp::try_from_sexp(sexp)?;
296 Ok(value as f32)
297 }
298 SEXPTYPE::REALSXP => {
299 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
300 Ok(value as f32)
301 }
302 SEXPTYPE::RAWSXP => {
303 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
304 Ok(value as f32)
305 }
306 SEXPTYPE::LGLSXP => {
307 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
308 Ok(value.to_i32() as f32)
309 }
310 _ => Err(SexpError::InvalidValue(format!(
311 "expected integer, numeric, logical, or raw; got {:?}",
312 actual
313 ))),
314 }
315 }
316
317 #[inline]
318 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
319 let actual = sexp.type_of();
320 match actual {
321 SEXPTYPE::INTSXP => {
322 let value: i32 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
323 Ok(value as f32)
324 }
325 SEXPTYPE::REALSXP => {
326 let value: f64 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
327 Ok(value as f32)
328 }
329 SEXPTYPE::RAWSXP => {
330 let value: u8 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
331 Ok(value as f32)
332 }
333 SEXPTYPE::LGLSXP => {
334 let value: RLogical = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
335 Ok(value.to_i32() as f32)
336 }
337 _ => Err(SexpError::InvalidValue(format!(
338 "expected integer, numeric, logical, or raw; got {:?}",
339 actual
340 ))),
341 }
342 }
343}
344
345impl TryFromSexp for Option<i8> {
346 type Error = SexpError;
347
348 #[inline]
349 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
350 try_from_sexp_numeric_option(sexp)
351 }
352
353 #[inline]
354 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
355 unsafe { try_from_sexp_numeric_option_unchecked(sexp) }
356 }
357}
358
359impl TryFromSexp for Option<i16> {
360 type Error = SexpError;
361
362 #[inline]
363 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
364 try_from_sexp_numeric_option(sexp)
365 }
366
367 #[inline]
368 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
369 unsafe { try_from_sexp_numeric_option_unchecked(sexp) }
370 }
371}
372
373impl TryFromSexp for Option<u16> {
374 type Error = SexpError;
375
376 #[inline]
377 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
378 try_from_sexp_numeric_option(sexp)
379 }
380
381 #[inline]
382 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
383 unsafe { try_from_sexp_numeric_option_unchecked(sexp) }
384 }
385}
386
387impl TryFromSexp for Option<u32> {
388 type Error = SexpError;
389
390 #[inline]
391 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
392 try_from_sexp_numeric_option(sexp)
393 }
394
395 #[inline]
396 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
397 unsafe { try_from_sexp_numeric_option_unchecked(sexp) }
398 }
399}
400
401impl TryFromSexp for Option<f32> {
402 type Error = SexpError;
403
404 #[inline]
405 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
406 if sexp.type_of() == SEXPTYPE::NILSXP {
407 return Ok(None);
408 }
409 let actual = sexp.type_of();
410 match actual {
411 SEXPTYPE::INTSXP => {
412 let value: i32 = TryFromSexp::try_from_sexp(sexp)?;
413 if value == crate::altrep_traits::NA_INTEGER {
414 Ok(None)
415 } else {
416 Ok(Some(value as f32))
417 }
418 }
419 SEXPTYPE::REALSXP => {
420 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
421 if is_na_real(value) {
422 Ok(None)
423 } else {
424 Ok(Some(value as f32))
425 }
426 }
427 SEXPTYPE::RAWSXP => {
428 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
429 Ok(Some(value as f32))
430 }
431 SEXPTYPE::LGLSXP => {
432 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
433 if value.is_na() {
434 Ok(None)
435 } else {
436 Ok(Some(value.to_i32() as f32))
437 }
438 }
439 _ => Err(SexpError::InvalidValue(format!(
440 "expected integer, numeric, logical, or raw; got {:?}",
441 actual
442 ))),
443 }
444 }
445
446 #[inline]
447 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
448 if sexp.type_of() == SEXPTYPE::NILSXP {
449 return Ok(None);
450 }
451 let actual = sexp.type_of();
452 match actual {
453 SEXPTYPE::INTSXP => {
454 let value: i32 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
455 if value == crate::altrep_traits::NA_INTEGER {
456 Ok(None)
457 } else {
458 Ok(Some(value as f32))
459 }
460 }
461 SEXPTYPE::REALSXP => {
462 let value: f64 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
463 if is_na_real(value) {
464 Ok(None)
465 } else {
466 Ok(Some(value as f32))
467 }
468 }
469 SEXPTYPE::RAWSXP => {
470 let value: u8 = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
471 Ok(Some(value as f32))
472 }
473 SEXPTYPE::LGLSXP => {
474 let value: RLogical = unsafe { TryFromSexp::try_from_sexp_unchecked(sexp)? };
475 if value.is_na() {
476 Ok(None)
477 } else {
478 Ok(Some(value.to_i32() as f32))
479 }
480 }
481 _ => Err(SexpError::InvalidValue(format!(
482 "expected integer, numeric, logical, or raw; got {:?}",
483 actual
484 ))),
485 }
486 }
487}
488impl TryFromSexp for i64 {
527 type Error = SexpError;
528
529 #[inline]
530 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
531 try_from_sexp_numeric_scalar(sexp)
532 }
533
534 #[inline]
535 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
536 unsafe { try_from_sexp_numeric_scalar_unchecked(sexp) }
537 }
538}
539
540impl TryFromSexp for u64 {
545 type Error = SexpError;
546
547 #[inline]
548 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
549 try_from_sexp_numeric_scalar(sexp)
550 }
551
552 #[inline]
553 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
554 unsafe { try_from_sexp_numeric_scalar_unchecked(sexp) }
555 }
556}
557
558impl TryFromSexp for Option<i64> {
560 type Error = SexpError;
561
562 #[inline]
563 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
564 try_from_sexp_numeric_option(sexp)
565 }
566
567 #[inline]
568 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
569 unsafe { try_from_sexp_numeric_option_unchecked(sexp) }
570 }
571}
572
573impl TryFromSexp for Option<u64> {
574 type Error = SexpError;
575
576 #[inline]
577 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
578 try_from_sexp_numeric_option(sexp)
579 }
580
581 #[inline]
582 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
583 unsafe { try_from_sexp_numeric_option_unchecked(sexp) }
584 }
585}
586
587impl TryFromSexp for usize {
588 type Error = SexpError;
589
590 #[inline]
591 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
592 let actual = sexp.type_of();
594 match actual {
595 SEXPTYPE::INTSXP => {
596 use crate::coerce::TryCoerce;
597 let value: i32 = TryFromSexp::try_from_sexp(sexp)?;
598 value
599 .try_coerce()
600 .map_err(|e| SexpError::InvalidValue(format!("{e}")))
601 }
602 SEXPTYPE::REALSXP => {
603 use crate::coerce::TryCoerce;
604 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
605 let u: u64 = value
606 .try_coerce()
607 .map_err(|e| SexpError::InvalidValue(format!("{e}")))?;
608 u.try_into()
609 .map_err(|_| SexpError::InvalidValue("value out of usize range".into()))
610 }
611 SEXPTYPE::RAWSXP => {
612 use crate::coerce::Coerce;
613 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
614 Ok(value.coerce())
615 }
616 SEXPTYPE::LGLSXP => {
617 use crate::coerce::TryCoerce;
618 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
619 value
620 .to_i32()
621 .try_coerce()
622 .map_err(|e| SexpError::InvalidValue(format!("{e}")))
623 }
624 _ => Err(SexpError::InvalidValue(format!(
625 "expected integer, numeric, logical, or raw; got {:?}",
626 actual
627 ))),
628 }
629 }
630}
631
632impl TryFromSexp for Option<usize> {
633 type Error = SexpError;
634
635 #[inline]
636 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
637 if sexp.type_of() == SEXPTYPE::NILSXP {
638 return Ok(None);
639 }
640 let actual = sexp.type_of();
641 match actual {
642 SEXPTYPE::INTSXP => {
643 use crate::coerce::TryCoerce;
644 let value: i32 = TryFromSexp::try_from_sexp(sexp)?;
645 if value == crate::altrep_traits::NA_INTEGER {
646 Ok(None)
647 } else {
648 value
649 .try_coerce()
650 .map(Some)
651 .map_err(|e| SexpError::InvalidValue(format!("{e}")))
652 }
653 }
654 SEXPTYPE::REALSXP => {
655 use crate::coerce::TryCoerce;
656 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
657 if is_na_real(value) {
658 return Ok(None);
659 }
660 let u: u64 = value
661 .try_coerce()
662 .map_err(|e| SexpError::InvalidValue(format!("{e}")))?;
663 u.try_into()
664 .map(Some)
665 .map_err(|_| SexpError::InvalidValue("value out of usize range".into()))
666 }
667 SEXPTYPE::RAWSXP => {
668 use crate::coerce::Coerce;
669 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
670 Ok(Some(value.coerce()))
671 }
672 SEXPTYPE::LGLSXP => {
673 use crate::coerce::TryCoerce;
674 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
675 if value.is_na() {
676 Ok(None)
677 } else {
678 value
679 .to_i32()
680 .try_coerce()
681 .map(Some)
682 .map_err(|e| SexpError::InvalidValue(format!("{e}")))
683 }
684 }
685 _ => Err(SexpError::InvalidValue(format!(
686 "expected integer, numeric, logical, or raw; got {:?}",
687 actual
688 ))),
689 }
690 }
691
692 #[inline]
693 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
694 Self::try_from_sexp(sexp)
695 }
696}
697
698impl TryFromSexp for isize {
699 type Error = SexpError;
700
701 #[inline]
702 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
703 let actual = sexp.type_of();
705 match actual {
706 SEXPTYPE::INTSXP => {
707 use crate::coerce::Coerce;
708 let value: i32 = TryFromSexp::try_from_sexp(sexp)?;
709 Ok(value.coerce())
710 }
711 SEXPTYPE::REALSXP => {
712 use crate::coerce::TryCoerce;
713 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
714 let i: i64 = value
715 .try_coerce()
716 .map_err(|e| SexpError::InvalidValue(format!("{e}")))?;
717 i.try_into()
718 .map_err(|_| SexpError::InvalidValue("value out of isize range".into()))
719 }
720 SEXPTYPE::RAWSXP => {
721 use crate::coerce::Coerce;
722 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
723 Ok(value.coerce())
724 }
725 SEXPTYPE::LGLSXP => {
726 use crate::coerce::Coerce;
727 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
728 Ok(value.to_i32().coerce())
729 }
730 _ => Err(SexpError::InvalidValue(format!(
731 "expected integer, numeric, logical, or raw; got {:?}",
732 actual
733 ))),
734 }
735 }
736}
737
738impl TryFromSexp for Option<isize> {
739 type Error = SexpError;
740
741 #[inline]
742 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
743 if sexp.type_of() == SEXPTYPE::NILSXP {
744 return Ok(None);
745 }
746 let actual = sexp.type_of();
747 match actual {
748 SEXPTYPE::INTSXP => {
749 use crate::coerce::Coerce;
750 let value: i32 = TryFromSexp::try_from_sexp(sexp)?;
751 if value == crate::altrep_traits::NA_INTEGER {
752 Ok(None)
753 } else {
754 Ok(Some(value.coerce()))
755 }
756 }
757 SEXPTYPE::REALSXP => {
758 use crate::coerce::TryCoerce;
759 let value: f64 = TryFromSexp::try_from_sexp(sexp)?;
760 if is_na_real(value) {
761 return Ok(None);
762 }
763 let i: i64 = value
764 .try_coerce()
765 .map_err(|e| SexpError::InvalidValue(format!("{e}")))?;
766 i.try_into()
767 .map(Some)
768 .map_err(|_| SexpError::InvalidValue("value out of isize range".into()))
769 }
770 SEXPTYPE::RAWSXP => {
771 use crate::coerce::Coerce;
772 let value: u8 = TryFromSexp::try_from_sexp(sexp)?;
773 Ok(Some(value.coerce()))
774 }
775 SEXPTYPE::LGLSXP => {
776 use crate::coerce::Coerce;
777 let value: RLogical = TryFromSexp::try_from_sexp(sexp)?;
778 if value.is_na() {
779 Ok(None)
780 } else {
781 Ok(Some(value.to_i32().coerce()))
782 }
783 }
784 _ => Err(SexpError::InvalidValue(format!(
785 "expected integer, numeric, logical, or raw; got {:?}",
786 actual
787 ))),
788 }
789 }
790
791 #[inline]
792 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
793 Self::try_from_sexp(sexp)
794 }
795}
796