extendr_api/robj/
try_from_robj.rs
1use super::*;
10use crate as extendr_api;
11use crate::conversions::try_into_int::FloatToInt;
12
13macro_rules! impl_try_from_scalar_integer {
14 ($t:ty) => {
15 impl TryFrom<&Robj> for $t {
16 type Error = Error;
17
18 fn try_from(robj: &Robj) -> Result<Self> {
20 match robj.len() {
22 0 => return Err(Error::ExpectedNonZeroLength(robj.clone())),
23 1 => {}
24 _ => return Err(Error::ExpectedScalar(robj.clone())),
25 };
26
27 if robj.is_na() {
29 return Err(Error::MustNotBeNA(robj.clone()));
30 }
31
32 if let Some(v) = robj.as_integer() {
37 return Self::try_from(v).map_err(|_| Error::OutOfLimits(robj.clone()));
38 }
39
40 if let Some(v) = robj.as_real() {
44 return v
45 .try_into_int()
46 .map_err(|conv_err| Error::ExpectedWholeNumber(robj.clone(), conv_err));
47 }
48
49 Err(Error::ExpectedNumeric(robj.clone()))
50 }
51 }
52 };
53}
54
55macro_rules! impl_try_from_scalar_real {
56 ($t:ty) => {
57 impl TryFrom<&Robj> for $t {
58 type Error = Error;
59
60 fn try_from(robj: &Robj) -> Result<Self> {
62 match robj.len() {
64 0 => return Err(Error::ExpectedNonZeroLength(robj.clone())),
65 1 => {}
66 _ => return Err(Error::ExpectedScalar(robj.clone())),
67 };
68
69 if robj.is_na() {
71 return Err(Error::MustNotBeNA(robj.clone()));
72 }
73
74 if let Some(v) = robj.as_real() {
78 return Ok(v as Self);
80 }
81 if let Some(v) = robj.as_integer() {
82 return Ok(v as Self);
84 }
85
86 Err(Error::ExpectedNumeric(robj.clone()))
87 }
88 }
89 };
90}
91
92impl_try_from_scalar_integer!(u8);
93impl_try_from_scalar_integer!(u16);
94impl_try_from_scalar_integer!(u32);
95impl_try_from_scalar_integer!(u64);
96impl_try_from_scalar_integer!(usize);
97impl_try_from_scalar_integer!(i8);
98impl_try_from_scalar_integer!(i16);
99impl_try_from_scalar_integer!(i32);
100impl_try_from_scalar_integer!(i64);
101impl_try_from_scalar_integer!(isize);
102impl_try_from_scalar_real!(f32);
103impl_try_from_scalar_real!(f64);
104
105impl TryFrom<&Robj> for bool {
106 type Error = Error;
107
108 fn try_from(robj: &Robj) -> Result<Self> {
111 if robj.is_na() {
112 Err(Error::MustNotBeNA(robj.clone()))
113 } else {
114 Ok(<Rbool>::try_from(robj)?.is_true())
115 }
116 }
117}
118
119impl TryFrom<&Robj> for &str {
120 type Error = Error;
121
122 fn try_from(robj: &Robj) -> Result<Self> {
125 if robj.is_na() {
126 return Err(Error::MustNotBeNA(robj.clone()));
127 }
128 match robj.len() {
129 0 => Err(Error::ExpectedNonZeroLength(robj.clone())),
130 1 => {
131 if let Some(s) = robj.as_str() {
132 Ok(s)
133 } else {
134 Err(Error::ExpectedString(robj.clone()))
135 }
136 }
137 _ => Err(Error::ExpectedScalar(robj.clone())),
138 }
139 }
140}
141
142impl TryFrom<&Robj> for String {
143 type Error = Error;
144
145 fn try_from(robj: &Robj) -> Result<Self> {
149 <&str>::try_from(robj).map(|s| s.to_string())
150 }
151}
152
153impl TryFrom<&Robj> for Vec<i32> {
154 type Error = Error;
155
156 fn try_from(robj: &Robj) -> Result<Self> {
160 if let Some(v) = robj.as_typed_slice() {
161 Ok(Vec::from(v))
163 } else {
164 Err(Error::ExpectedInteger(robj.clone()))
165 }
166 }
167}
168
169impl TryFrom<&Robj> for Vec<f64> {
170 type Error = Error;
171
172 fn try_from(robj: &Robj) -> Result<Self> {
176 if let Some(v) = robj.as_typed_slice() {
177 Ok(Vec::from(v))
179 } else {
180 Err(Error::ExpectedReal(robj.clone()))
181 }
182 }
183}
184
185impl TryFrom<&Robj> for Vec<u8> {
186 type Error = Error;
187
188 fn try_from(robj: &Robj) -> Result<Self> {
191 if let Some(v) = robj.as_typed_slice() {
192 Ok(Vec::from(v))
193 } else {
194 Err(Error::ExpectedRaw(robj.clone()))
195 }
196 }
197}
198
199impl TryFrom<&Robj> for Vec<Rint> {
200 type Error = Error;
201
202 fn try_from(robj: &Robj) -> Result<Self> {
206 if let Some(v) = robj.as_typed_slice() {
207 Ok(Vec::from(v))
208 } else {
209 Err(Error::ExpectedInteger(robj.clone()))
210 }
211 }
212}
213
214impl TryFrom<&Robj> for Vec<Rfloat> {
215 type Error = Error;
216
217 fn try_from(robj: &Robj) -> Result<Self> {
221 if let Some(v) = robj.as_typed_slice() {
222 Ok(Vec::from(v))
223 } else {
224 Err(Error::ExpectedReal(robj.clone()))
225 }
226 }
227}
228
229impl TryFrom<&Robj> for Vec<Rbool> {
230 type Error = Error;
231
232 fn try_from(robj: &Robj) -> Result<Self> {
236 if let Some(v) = robj.as_typed_slice() {
237 Ok(Vec::from(v))
238 } else {
239 Err(Error::ExpectedInteger(robj.clone()))
240 }
241 }
242}
243
244impl TryFrom<&Robj> for Vec<Rcplx> {
245 type Error = Error;
246
247 fn try_from(robj: &Robj) -> Result<Self> {
249 if let Some(v) = robj.as_typed_slice() {
250 Ok(Vec::from(v))
251 } else {
252 Err(Error::ExpectedComplex(robj.clone()))
253 }
254 }
255}
256
257impl TryFrom<&Robj> for Vec<String> {
258 type Error = Error;
259
260 fn try_from(robj: &Robj) -> Result<Self> {
263 if let Some(iter) = robj.as_str_iter() {
264 if iter.clone().any(|s| s.is_na()) {
266 Err(Error::MustNotBeNA(robj.clone()))
267 } else {
268 Ok(iter.map(|s| s.to_string()).collect::<Vec<String>>())
269 }
270 } else {
271 Err(Error::ExpectedString(robj.clone()))
272 }
273 }
274}
275
276impl TryFrom<&Robj> for &[i32] {
277 type Error = Error;
278
279 fn try_from(robj: &Robj) -> Result<Self> {
282 robj.as_typed_slice()
283 .ok_or_else(|| Error::ExpectedInteger(robj.clone()))
284 }
285}
286
287impl TryFrom<&Robj> for &[Rint] {
288 type Error = Error;
289
290 fn try_from(robj: &Robj) -> Result<Self> {
293 robj.as_typed_slice()
294 .ok_or_else(|| Error::ExpectedInteger(robj.clone()))
295 }
296}
297
298impl TryFrom<&Robj> for &[Rfloat] {
299 type Error = Error;
300
301 fn try_from(robj: &Robj) -> Result<Self> {
304 robj.as_typed_slice()
305 .ok_or_else(|| Error::ExpectedReal(robj.clone()))
306 }
307}
308
309impl TryFrom<&Robj> for &[Rbool] {
310 type Error = Error;
311
312 fn try_from(robj: &Robj) -> Result<Self> {
315 robj.as_typed_slice()
316 .ok_or_else(|| Error::ExpectedLogical(robj.clone()))
317 }
318}
319
320impl TryFrom<&Robj> for &[Rcplx] {
321 type Error = Error;
322
323 fn try_from(robj: &Robj) -> Result<Self> {
326 robj.as_typed_slice()
327 .ok_or_else(|| Error::ExpectedComplex(robj.clone()))
328 }
329}
330
331impl TryFrom<&Robj> for &[u8] {
332 type Error = Error;
333
334 fn try_from(robj: &Robj) -> Result<Self> {
336 robj.as_typed_slice()
337 .ok_or_else(|| Error::ExpectedRaw(robj.clone()))
338 }
339}
340
341impl TryFrom<&Robj> for &[f64] {
342 type Error = Error;
343
344 fn try_from(robj: &Robj) -> Result<Self> {
347 robj.as_typed_slice()
348 .ok_or_else(|| Error::ExpectedReal(robj.clone()))
349 }
350}
351
352impl TryFrom<&mut Robj> for &mut [i32] {
353 type Error = Error;
354
355 fn try_from(robj: &mut Robj) -> Result<Self> {
358 robj.as_typed_slice_mut()
359 .ok_or_else(|| Error::ExpectedInteger(robj.clone()))
360 }
361}
362
363impl TryFrom<&mut Robj> for &mut [Rint] {
364 type Error = Error;
365
366 fn try_from(robj: &mut Robj) -> Result<Self> {
369 robj.as_typed_slice_mut()
370 .ok_or_else(|| Error::ExpectedInteger(robj.clone()))
371 }
372}
373
374impl TryFrom<&mut Robj> for &mut [Rfloat] {
375 type Error = Error;
376
377 fn try_from(robj: &mut Robj) -> Result<Self> {
380 robj.as_typed_slice_mut()
381 .ok_or_else(|| Error::ExpectedReal(robj.clone()))
382 }
383}
384
385impl TryFrom<&mut Robj> for &mut [Rbool] {
386 type Error = Error;
387
388 fn try_from(robj: &mut Robj) -> Result<Self> {
391 robj.as_typed_slice_mut()
392 .ok_or_else(|| Error::ExpectedLogical(robj.clone()))
393 }
394}
395
396impl TryFrom<&mut Robj> for &mut [Rcplx] {
397 type Error = Error;
398
399 fn try_from(robj: &mut Robj) -> Result<Self> {
402 robj.as_typed_slice_mut()
403 .ok_or_else(|| Error::ExpectedComplex(robj.clone()))
404 }
405}
406
407impl TryFrom<&mut Robj> for &mut [u8] {
408 type Error = Error;
409
410 fn try_from(robj: &mut Robj) -> Result<Self> {
412 robj.as_typed_slice_mut()
413 .ok_or_else(|| Error::ExpectedRaw(robj.clone()))
414 }
415}
416
417impl TryFrom<&mut Robj> for &mut [f64] {
418 type Error = Error;
419
420 fn try_from(robj: &mut Robj) -> Result<Self> {
423 robj.as_typed_slice_mut()
424 .ok_or_else(|| Error::ExpectedReal(robj.clone()))
425 }
426}
427
428impl TryFrom<&Robj> for Rcplx {
429 type Error = Error;
430
431 fn try_from(robj: &Robj) -> Result<Self> {
432 match robj.len() {
434 0 => return Err(Error::ExpectedNonZeroLength(robj.clone())),
435 1 => {}
436 _ => return Err(Error::ExpectedScalar(robj.clone())),
437 };
438
439 if robj.is_na() {
441 return Ok(Rcplx::na());
442 }
443
444 if let Some(v) = robj.as_real() {
446 return Ok(Rcplx::from(v));
447 }
448
449 if let Some(v) = robj.as_integer() {
452 return Ok(Rcplx::from(v as f64));
453 }
454
455 if let Some(s) = robj.as_typed_slice() {
457 return Ok(s[0]);
458 }
459
460 Err(Error::ExpectedComplex(robj.clone()))
461 }
462}
463
464macro_rules! impl_try_from_robj {
467 (&mut [$type:ty]) => {
468 impl TryFrom<Robj> for &mut [$type] {
469 type Error = Error;
470
471 fn try_from(mut robj: Robj) -> Result<Self> {
472 Self::try_from(&mut robj)
473 }
474 }
475
476 impl TryFrom<&mut Robj> for Option<&mut [$type]> {
477 type Error = Error;
478
479 fn try_from(robj: &mut Robj) -> Result<Self> {
480 if robj.is_null() || robj.is_na() {
481 Ok(None)
482 } else {
483 Ok(Some(<&mut [$type]>::try_from(robj)?))
484 }
485 }
486 }
487
488 impl TryFrom<Robj> for Option<&mut [$type]> {
489 type Error = Error;
490
491 fn try_from(mut robj: Robj) -> Result<Self> {
492 Self::try_from(&mut robj)
493 }
494 }
495 };
496 ($(@generics<$generics:tt>)? $type:ty $(where $($where_clause:tt)*)?) => {
497 impl$(<$generics>)? TryFrom<Robj> for $type $(where $($where_clause)*)? {
498 type Error = Error;
499
500 fn try_from(robj: Robj) -> Result<Self> {
501 Self::try_from(&robj)
502 }
503 }
504
505 impl$(<$generics>)? TryFrom<&Robj> for Option<$type> $(where $($where_clause)*)? {
506 type Error = Error;
507
508 fn try_from(robj: &Robj) -> Result<Self> {
509 if robj.is_null() || robj.is_na() {
510 Ok(None)
511 } else {
512 Ok(Some(<$type>::try_from(robj)?))
513 }
514 }
515 }
516
517 impl$(<$generics>)? TryFrom<Robj> for Option<$type> $(where $($where_clause)*)? {
518 type Error = Error;
519
520 fn try_from(robj: Robj) -> Result<Self> {
521 Self::try_from(&robj)
522 }
523 }
524 };
525}
526#[rustfmt::skip]
527impl_try_from_robj!(u8);
528impl_try_from_robj!(u16);
529impl_try_from_robj!(u32);
530impl_try_from_robj!(u64);
531impl_try_from_robj!(usize);
532
533impl_try_from_robj!(i8);
534impl_try_from_robj!(i16);
535impl_try_from_robj!(i32);
536impl_try_from_robj!(i64);
537impl_try_from_robj!(isize);
538
539impl_try_from_robj!(bool);
540
541impl_try_from_robj!(Rint);
542impl_try_from_robj!(Rfloat);
543impl_try_from_robj!(Rbool);
544impl_try_from_robj!(Rcplx);
545
546impl_try_from_robj!(f32);
547impl_try_from_robj!(f64);
548
549impl_try_from_robj!(Vec::<String>);
550impl_try_from_robj!(Vec::<Rint>);
551impl_try_from_robj!(Vec::<Rfloat>);
552impl_try_from_robj!(Vec::<Rbool>);
553impl_try_from_robj!(Vec::<Rcplx>);
554impl_try_from_robj!(Vec::<u8>);
555impl_try_from_robj!(Vec::<i32>);
556impl_try_from_robj!(Vec::<f64>);
557
558impl_try_from_robj!(&[Rint]);
559impl_try_from_robj!(&[Rfloat]);
560impl_try_from_robj!(&[Rbool]);
561impl_try_from_robj!(&[Rcplx]);
562impl_try_from_robj!(&[u8]);
563impl_try_from_robj!(&[i32]);
564impl_try_from_robj!(&[f64]);
565
566impl_try_from_robj!(&mut [Rint]);
567impl_try_from_robj!(&mut [Rfloat]);
568impl_try_from_robj!(&mut [Rbool]);
569impl_try_from_robj!(&mut [Rcplx]);
570impl_try_from_robj!(&mut [u8]);
571impl_try_from_robj!(&mut [i32]);
572impl_try_from_robj!(&mut [f64]);
573
574impl_try_from_robj!(&str);
575impl_try_from_robj!(String);
576
577impl_try_from_robj!(@generics<T> HashMap::<&str, T> where T: TryFrom<Robj, Error = error::Error>);
578impl_try_from_robj!(@generics<T> HashMap::<String,T> where T: TryFrom<Robj, Error = error::Error>);
579
580impl_try_from_robj!(HashMap::<&str, Robj>);
581impl_try_from_robj!(HashMap::<String, Robj>);
582
583impl<T> TryFrom<&Robj> for HashMap<&str, T>
588where
589 T: TryFrom<Robj, Error = error::Error>,
590{
591 type Error = Error;
592
593 fn try_from(value: &Robj) -> Result<Self> {
594 let value: List = value.try_into()?;
595
596 let value = value
597 .iter()
598 .map(|(name, value)| -> Result<(&str, T)> { value.try_into().map(|x| (name, x)) })
599 .collect::<Result<HashMap<_, _>>>()?;
600
601 Ok(value)
602 }
603}
604
605impl<T> TryFrom<&Robj> for HashMap<String, T>
606where
607 T: TryFrom<Robj, Error = error::Error>,
608{
609 type Error = Error;
610 fn try_from(value: &Robj) -> Result<Self> {
611 let value: HashMap<&str, _> = value.try_into()?;
612 Ok(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
613 }
614}
615
616macro_rules! impl_try_from_robj_for_arrays {
617 ($slice_type:ty) => {
618 impl<const N: usize> TryFrom<&Robj> for [$slice_type; N] {
619 type Error = Error;
620
621 fn try_from(value: &Robj) -> Result<Self> {
622 let value: &[$slice_type] = value.try_into()?;
623 if value.len() != N {
624 return Err(Error::ExpectedLength(N));
625 }
626 let value: Self = value
627 .try_into()
628 .map_err(|error| format!("{}", error).to_string())?;
629 Ok(value)
630 }
631 }
632
633 impl<const N: usize> TryFrom<Robj> for [$slice_type; N] {
636 type Error = Error;
637
638 fn try_from(robj: Robj) -> Result<Self> {
639 Self::try_from(&robj)
640 }
641 }
642
643 impl<const N: usize> TryFrom<&Robj> for Option<[$slice_type; N]> {
644 type Error = Error;
645
646 fn try_from(robj: &Robj) -> Result<Self> {
647 if robj.is_null() || robj.is_na() {
648 Ok(None)
649 } else {
650 Ok(Some(<[$slice_type; N]>::try_from(robj)?))
651 }
652 }
653 }
654
655 impl<const N: usize> TryFrom<Robj> for Option<[$slice_type; N]> {
656 type Error = Error;
657
658 fn try_from(robj: Robj) -> Result<Self> {
659 Self::try_from(&robj)
660 }
661 }
662 };
663}
664
665impl_try_from_robj_for_arrays!(Rint);
666impl_try_from_robj_for_arrays!(Rfloat);
667impl_try_from_robj_for_arrays!(Rbool);
668impl_try_from_robj_for_arrays!(Rcplx);
669impl_try_from_robj_for_arrays!(u8);
670impl_try_from_robj_for_arrays!(i32);
671impl_try_from_robj_for_arrays!(f64);
672
673impl_try_from_robj_tuples!((1, 12));
675
676impl TryFrom<&Robj> for HashMap<&str, Robj> {
680 type Error = Error;
681
682 fn try_from(value: &Robj) -> Result<Self> {
683 let value: List = value.try_into()?;
684 Ok(value.into_iter().collect())
685 }
686}
687
688impl TryFrom<&Robj> for HashMap<String, Robj> {
689 type Error = Error;
690 fn try_from(value: &Robj) -> Result<Self> {
691 let value: HashMap<&str, _> = value.try_into()?;
692 Ok(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
693 }
694}