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
92macro_rules! impl_typed_slice_conversions {
93 ($type:ty, $error:ident, $desc:expr) => {
94 impl_typed_slice_conversions!($type, $error, $error, $error, $desc);
95 };
96 ($type:ty, $vec_error:ident, $slice_error:ident, $mut_error:ident, $desc:expr) => {
97 impl TryFrom<&Robj> for Vec<$type> {
98 type Error = Error;
99
100 #[doc = concat!("Convert ", $desc, " into `Vec<", stringify!($type), ">`.")]
101 #[doc = "Note: Unless you plan to store the result, use a slice instead."]
102 fn try_from(robj: &Robj) -> Result<Self> {
103 robj.as_typed_slice()
104 .map(<[_]>::to_vec)
105 .ok_or_else(|| Error::$vec_error(robj.clone()))
106 }
107 }
108
109 impl TryFrom<&Robj> for &[$type] {
110 type Error = Error;
111
112 #[doc = concat!("Convert ", $desc, " into `&[", stringify!($type), "]`.")]
113 fn try_from(robj: &Robj) -> Result<Self> {
114 robj.as_typed_slice()
115 .ok_or_else(|| Error::$slice_error(robj.clone()))
116 }
117 }
118
119 impl TryFrom<&mut Robj> for &mut [$type] {
120 type Error = Error;
121
122 #[doc = concat!("Convert ", $desc, " into `&mut [", stringify!($type), "]`.")]
123 fn try_from(robj: &mut Robj) -> Result<Self> {
124 robj.as_typed_slice_mut()
125 .ok_or_else(|| Error::$mut_error(robj.clone()))
126 }
127 }
128
129 impl TryFrom<&Robj> for Option<&[$type]> {
130 type Error = Error;
131
132 #[doc = concat!("Convert ", $desc, " into `Option<&[", stringify!($type), "]>`.")]
133 fn try_from(robj: &Robj) -> Result<Self> {
134 if robj.is_null() || robj.is_na() {
135 Ok(None)
136 } else {
137 Ok(Some(<&[$type]>::try_from(robj)?))
138 }
139 }
140 }
141
142 impl TryFrom<&mut Robj> for Option<&mut [$type]> {
143 type Error = Error;
144
145 #[doc = concat!("Convert ", $desc, " into `Option<&mut [", stringify!($type), "]>`.")]
146 fn try_from(robj: &mut Robj) -> Result<Self> {
147 if robj.is_null() || robj.is_na() {
148 Ok(None)
149 } else {
150 Ok(Some(<&mut [$type]>::try_from(robj)?))
151 }
152 }
153 }
154
155 impl TryFrom<&Robj> for &$type {
156 type Error = Error;
157
158 #[doc = concat!("Convert ", $desc, " into `&", stringify!($type), "`.")]
159 fn try_from(robj: &Robj) -> Result<Self> {
160 let slice: &[$type] = robj.try_into()?;
161
162 if slice.is_empty() {
163 return Err(Error::ExpectedNonZeroLength(robj.clone()));
164 }
165 if slice.len() != 1 {
166 return Err(Error::ExpectedScalar(robj.clone()));
167 }
168 let Some(value) = slice.get(0) else {
169 unreachable!()
170 };
171 if value.is_na() {
172 return Err(Error::MustNotBeNA(robj.clone()));
173 }
174 Ok(value)
175 }
176 }
177
178 impl TryFrom<&mut Robj> for &mut $type {
179 type Error = Error;
180
181 #[doc = concat!("Convert ", $desc, " into `&mut ", stringify!($type), "`.")]
182 fn try_from(robj: &mut Robj) -> Result<Self> {
183 let slice: &mut [$type] = robj.try_into()?;
184
185 if slice.is_empty() {
186 return Err(Error::ExpectedNonZeroLength(robj.clone()));
187 }
188 if slice.len() != 1 {
189 return Err(Error::ExpectedScalar(robj.clone()));
190 }
191 let Some(value) = slice.get_mut(0) else {
192 unreachable!()
193 };
194 if value.is_na() {
195 return Err(Error::MustNotBeNA(robj.clone()));
196 }
197 Ok(value)
198 }
199 }
200 };
201}
202
203impl_try_from_scalar_integer!(u8);
204impl_try_from_scalar_integer!(u16);
205impl_try_from_scalar_integer!(u32);
206impl_try_from_scalar_integer!(u64);
207impl_try_from_scalar_integer!(usize);
208impl_try_from_scalar_integer!(i8);
209impl_try_from_scalar_integer!(i16);
210impl_try_from_scalar_integer!(i32);
211impl_try_from_scalar_integer!(i64);
212impl_try_from_scalar_integer!(isize);
213impl_try_from_scalar_real!(f32);
214impl_try_from_scalar_real!(f64);
215
216impl TryFrom<&Robj> for bool {
217 type Error = Error;
218
219 fn try_from(robj: &Robj) -> Result<Self> {
222 if robj.is_na() {
223 Err(Error::MustNotBeNA(robj.clone()))
224 } else {
225 Ok(<Rbool>::try_from(robj)?.is_true())
226 }
227 }
228}
229
230impl TryFrom<&Robj> for &str {
231 type Error = Error;
232
233 fn try_from(robj: &Robj) -> Result<Self> {
236 if robj.is_na() {
237 return Err(Error::MustNotBeNA(robj.clone()));
238 }
239 match robj.len() {
240 0 => Err(Error::ExpectedNonZeroLength(robj.clone())),
241 1 => {
242 if let Some(s) = robj.as_str() {
243 Ok(s)
244 } else {
245 Err(Error::ExpectedString(robj.clone()))
246 }
247 }
248 _ => Err(Error::ExpectedScalar(robj.clone())),
249 }
250 }
251}
252
253impl TryFrom<&Robj> for Option<&str> {
254 type Error = Error;
255
256 fn try_from(robj: &Robj) -> Result<Self> {
257 if robj.is_null() || robj.is_na() {
258 Ok(None)
259 } else {
260 Ok(Some(<&str>::try_from(robj)?))
261 }
262 }
263}
264
265impl TryFrom<&Robj> for String {
266 type Error = Error;
267
268 fn try_from(robj: &Robj) -> Result<Self> {
272 <&str>::try_from(robj).map(|s| s.to_string())
273 }
274}
275
276impl_typed_slice_conversions!(i32, ExpectedInteger, "an INTSXP object");
277impl_typed_slice_conversions!(Rint, ExpectedInteger, "an INTSXP object");
278impl_typed_slice_conversions!(Rfloat, ExpectedReal, "a REALSXP object");
279impl_typed_slice_conversions!(
280 Rbool,
281 ExpectedInteger,
282 ExpectedLogical,
283 ExpectedLogical,
284 "a LGLSXP object"
285);
286impl_typed_slice_conversions!(Rcplx, ExpectedComplex, "a complex object");
287impl_typed_slice_conversions!(u8, ExpectedRaw, "a RAWSXP object");
288impl_typed_slice_conversions!(f64, ExpectedReal, "a REALSXP object");
289
290impl TryFrom<&Robj> for Vec<String> {
291 type Error = Error;
292
293 fn try_from(robj: &Robj) -> Result<Self> {
296 if let Some(iter) = robj.as_str_iter() {
297 if iter.clone().any(|s| s.is_na()) {
299 Err(Error::MustNotBeNA(robj.clone()))
300 } else {
301 Ok(iter.map(|s| s.to_string()).collect::<Vec<String>>())
302 }
303 } else {
304 Err(Error::ExpectedString(robj.clone()))
305 }
306 }
307}
308
309impl TryFrom<&Robj> for Rcplx {
310 type Error = Error;
311
312 fn try_from(robj: &Robj) -> Result<Self> {
313 match robj.len() {
315 0 => return Err(Error::ExpectedNonZeroLength(robj.clone())),
316 1 => {}
317 _ => return Err(Error::ExpectedScalar(robj.clone())),
318 };
319
320 if robj.is_na() {
322 return Ok(Rcplx::na());
323 }
324
325 if let Some(v) = robj.as_real() {
327 return Ok(Rcplx::from(v));
328 }
329
330 if let Some(v) = robj.as_integer() {
333 return Ok(Rcplx::from(v as f64));
334 }
335
336 if let Some(s) = robj.as_typed_slice() {
338 return Ok(s[0]);
339 }
340
341 Err(Error::ExpectedComplex(robj.clone()))
342 }
343}
344
345macro_rules! impl_try_from_robj {
348 ($(@generics<$generics:tt>)? $type:ty $(where $($where_clause:tt)*)?) => {
349 impl$(<$generics>)? TryFrom<Robj> for $type $(where $($where_clause)*)? {
350 type Error = Error;
351
352 fn try_from(robj: Robj) -> Result<Self> {
353 Self::try_from(&robj)
354 }
355 }
356
357 impl$(<$generics>)? TryFrom<&Robj> for Option<$type> $(where $($where_clause)*)? {
358 type Error = Error;
359
360 fn try_from(robj: &Robj) -> Result<Self> {
361 if robj.is_null() || robj.is_na() {
362 Ok(None)
363 } else {
364 Ok(Some(<$type>::try_from(robj)?))
365 }
366 }
367 }
368
369 impl$(<$generics>)? TryFrom<Robj> for Option<$type> $(where $($where_clause)*)? {
370 type Error = Error;
371
372 fn try_from(robj: Robj) -> Result<Self> {
373 Self::try_from(&robj)
374 }
375 }
376 };
377}
378#[rustfmt::skip]
379impl_try_from_robj!(u8);
380impl_try_from_robj!(u16);
381impl_try_from_robj!(u32);
382impl_try_from_robj!(u64);
383impl_try_from_robj!(usize);
384
385impl_try_from_robj!(i8);
386impl_try_from_robj!(i16);
387impl_try_from_robj!(i32);
388impl_try_from_robj!(i64);
389impl_try_from_robj!(isize);
390
391impl_try_from_robj!(bool);
392
393impl_try_from_robj!(Rint);
394impl_try_from_robj!(Rfloat);
395impl_try_from_robj!(Rbool);
396impl_try_from_robj!(Rcplx);
397
398impl_try_from_robj!(f32);
399impl_try_from_robj!(f64);
400
401impl_try_from_robj!(Vec::<String>);
402impl_try_from_robj!(Vec::<Rint>);
403impl_try_from_robj!(Vec::<Rfloat>);
404impl_try_from_robj!(Vec::<Rbool>);
405impl_try_from_robj!(Vec::<Rcplx>);
406impl_try_from_robj!(Vec::<u8>);
407impl_try_from_robj!(Vec::<i32>);
408impl_try_from_robj!(Vec::<f64>);
409
410impl_try_from_robj!(String);
411
412impl_try_from_robj!(@generics<T> HashMap::<&str, T> where T: TryFrom<Robj, Error = error::Error>);
413impl_try_from_robj!(@generics<T> HashMap::<String,T> where T: TryFrom<Robj, Error = error::Error>);
414
415impl_try_from_robj!(HashMap::<&str, Robj>);
416impl_try_from_robj!(HashMap::<String, Robj>);
417
418impl TryFrom<&Robj> for Option<()> {
419 type Error = Error;
420
421 fn try_from(value: &Robj) -> Result<Self> {
422 if value.is_null() {
423 Ok(Some(()))
424 } else {
425 Err(Error::ExpectedNull(value.clone()))
426 }
427 }
428}
429
430impl TryFrom<Robj> for Option<()> {
431 type Error = Error;
432 fn try_from(robj: Robj) -> Result<Self> {
433 Self::try_from(&robj)
434 }
435}
436
437impl<T> TryFrom<&Robj> for HashMap<&str, T>
438where
439 T: TryFrom<Robj, Error = error::Error>,
440{
441 type Error = Error;
442
443 fn try_from(value: &Robj) -> Result<Self> {
444 let value: List = value.try_into()?;
445
446 let value = value
447 .iter()
448 .map(|(name, value)| -> Result<(&str, T)> { value.try_into().map(|x| (name, x)) })
449 .collect::<Result<HashMap<_, _>>>()?;
450
451 Ok(value)
452 }
453}
454
455impl<T> TryFrom<&Robj> for HashMap<String, T>
456where
457 T: TryFrom<Robj, Error = error::Error>,
458{
459 type Error = Error;
460 fn try_from(value: &Robj) -> Result<Self> {
461 let value: HashMap<&str, _> = value.try_into()?;
462 Ok(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
463 }
464}
465
466macro_rules! impl_try_from_robj_for_arrays {
467 ($slice_type:ty) => {
468 impl<const N: usize> TryFrom<&Robj> for [$slice_type; N] {
469 type Error = Error;
470
471 fn try_from(value: &Robj) -> Result<Self> {
472 let value: &[$slice_type] = value.try_into()?;
473 if value.len() != N {
474 return Err(Error::ExpectedLength(N));
475 }
476 let value: Self = value
477 .try_into()
478 .map_err(|error| format!("{}", error).to_string())?;
479 Ok(value)
480 }
481 }
482
483 impl<const N: usize> TryFrom<Robj> for [$slice_type; N] {
486 type Error = Error;
487
488 fn try_from(robj: Robj) -> Result<Self> {
489 Self::try_from(&robj)
490 }
491 }
492
493 impl<const N: usize> TryFrom<&Robj> for Option<[$slice_type; N]> {
494 type Error = Error;
495
496 fn try_from(robj: &Robj) -> Result<Self> {
497 if robj.is_null() || robj.is_na() {
498 Ok(None)
499 } else {
500 Ok(Some(<[$slice_type; N]>::try_from(robj)?))
501 }
502 }
503 }
504
505 impl<const N: usize> TryFrom<Robj> for Option<[$slice_type; N]> {
506 type Error = Error;
507
508 fn try_from(robj: Robj) -> Result<Self> {
509 Self::try_from(&robj)
510 }
511 }
512 };
513}
514
515impl_try_from_robj_for_arrays!(Rint);
516impl_try_from_robj_for_arrays!(Rfloat);
517impl_try_from_robj_for_arrays!(Rbool);
518impl_try_from_robj_for_arrays!(Rcplx);
519impl_try_from_robj_for_arrays!(u8);
520impl_try_from_robj_for_arrays!(i32);
521impl_try_from_robj_for_arrays!(f64);
522
523impl<T0> TryFrom<&Robj> for (T0,)
529where
530 T0: for<'a> TryFrom<&'a Robj, Error = Error>,
531{
532 type Error = Error;
533
534 fn try_from(robj: &Robj) -> Result<Self> {
535 let list: List = robj.try_into()?;
536 if list.len() != 1 {
537 return Err(Error::ExpectedLength(1));
538 }
539 Ok(((&list.elt(0)?).try_into()?,))
540 }
541}
542
543impl<T0> TryFrom<Robj> for (T0,)
544where
545 T0: for<'a> TryFrom<&'a Robj, Error = Error>,
546{
547 type Error = Error;
548
549 fn try_from(robj: Robj) -> Result<Self> {
550 Self::try_from(&robj)
551 }
552}
553
554impl<T0> TryFrom<&Robj> for Option<(T0,)>
555where
556 T0: for<'a> TryFrom<&'a Robj, Error = Error>,
557{
558 type Error = Error;
559
560 fn try_from(robj: &Robj) -> Result<Self> {
561 if robj.is_null() || robj.is_na() {
562 Ok(None)
563 } else {
564 <(T0,)>::try_from(robj).map(Some)
565 }
566 }
567}
568
569impl<T0> TryFrom<Robj> for Option<(T0,)>
570where
571 T0: for<'a> TryFrom<&'a Robj, Error = Error>,
572{
573 type Error = Error;
574
575 fn try_from(robj: Robj) -> Result<Self> {
576 Self::try_from(&robj)
577 }
578}
579
580impl_try_from_robj_tuples!((2, 12));
581
582impl TryFrom<&Robj> for HashMap<&str, Robj> {
585 type Error = Error;
586
587 fn try_from(value: &Robj) -> Result<Self> {
588 let value: List = value.try_into()?;
589 Ok(value.into_iter().collect())
590 }
591}
592
593impl TryFrom<&Robj> for HashMap<String, Robj> {
594 type Error = Error;
595 fn try_from(value: &Robj) -> Result<Self> {
596 let value: HashMap<&str, _> = value.try_into()?;
597 Ok(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
598 }
599}