1use crate::altrep_traits::{NA_INTEGER, NA_LOGICAL, NA_REAL};
7use crate::into_r::IntoR;
8impl IntoR for i64 {
38 type Error = std::convert::Infallible;
39 #[inline]
40 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
41 Ok(self.into_sexp())
42 }
43 #[inline]
44 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
45 Ok(unsafe { self.into_sexp_unchecked() })
46 }
47 #[inline]
48 fn into_sexp(self) -> crate::ffi::SEXP {
49 if self > i32::MIN as i64 && self <= i32::MAX as i64 {
51 (self as i32).into_sexp()
53 } else {
54 (self as f64).into_sexp()
56 }
57 }
58 #[inline]
59 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
60 if self > i32::MIN as i64 && self <= i32::MAX as i64 {
61 unsafe { (self as i32).into_sexp_unchecked() }
62 } else {
63 unsafe { (self as f64).into_sexp_unchecked() }
64 }
65 }
66}
67
68impl IntoR for u64 {
73 type Error = std::convert::Infallible;
74 #[inline]
75 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
76 Ok(self.into_sexp())
77 }
78 #[inline]
79 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
80 Ok(unsafe { self.into_sexp_unchecked() })
81 }
82 #[inline]
83 fn into_sexp(self) -> crate::ffi::SEXP {
84 if self <= i32::MAX as u64 {
85 (self as i32).into_sexp()
86 } else {
87 (self as f64).into_sexp()
88 }
89 }
90 #[inline]
91 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
92 if self <= i32::MAX as u64 {
93 unsafe { (self as i32).into_sexp_unchecked() }
94 } else {
95 unsafe { (self as f64).into_sexp_unchecked() }
96 }
97 }
98}
99
100impl IntoR for isize {
105 type Error = std::convert::Infallible;
106 #[inline]
107 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
108 Ok((self as i64).into_sexp())
109 }
110 #[inline]
111 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
112 Ok(unsafe { self.into_sexp_unchecked() })
113 }
114 #[inline]
115 fn into_sexp(self) -> crate::ffi::SEXP {
116 (self as i64).into_sexp()
117 }
118 #[inline]
119 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
120 unsafe { (self as i64).into_sexp_unchecked() }
121 }
122}
123
124impl IntoR for usize {
129 type Error = std::convert::Infallible;
130 #[inline]
131 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
132 Ok((self as u64).into_sexp())
133 }
134 #[inline]
135 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
136 Ok(unsafe { self.into_sexp_unchecked() })
137 }
138 #[inline]
139 fn into_sexp(self) -> crate::ffi::SEXP {
140 (self as u64).into_sexp()
141 }
142 #[inline]
143 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
144 unsafe { (self as u64).into_sexp_unchecked() }
145 }
146}
147
148macro_rules! impl_logical_into_r {
150 ($ty:ty, $to_i32:expr) => {
151 impl IntoR for $ty {
152 type Error = std::convert::Infallible;
153 #[inline]
154 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
155 Ok(crate::ffi::SEXP::scalar_logical_raw($to_i32(self)))
156 }
157 #[inline]
158 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
159 Ok(unsafe { self.into_sexp_unchecked() })
160 }
161 #[inline]
162 fn into_sexp(self) -> crate::ffi::SEXP {
163 crate::ffi::SEXP::scalar_logical_raw($to_i32(self))
164 }
165 #[inline]
166 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
167 unsafe { crate::ffi::Rf_ScalarLogical_unchecked($to_i32(self)) }
168 }
169 }
170 };
171}
172
173impl_logical_into_r!(bool, |v: bool| i32::from(v));
174impl_logical_into_r!(crate::ffi::Rboolean, |v: crate::ffi::Rboolean| v as i32);
175impl_logical_into_r!(crate::ffi::RLogical, crate::ffi::RLogical::to_i32);
176
177impl IntoR for Option<i32> {
178 type Error = std::convert::Infallible;
179 #[inline]
180 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
181 Ok(self.into_sexp())
182 }
183 #[inline]
184 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
185 Ok(unsafe { self.into_sexp_unchecked() })
186 }
187 #[inline]
188 fn into_sexp(self) -> crate::ffi::SEXP {
189 match self {
190 Some(v) => v.into_sexp(),
191 None => crate::ffi::SEXP::scalar_integer(NA_INTEGER),
192 }
193 }
194 #[inline]
195 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
196 match self {
197 Some(v) => unsafe { v.into_sexp_unchecked() },
198 None => unsafe { crate::ffi::Rf_ScalarInteger_unchecked(NA_INTEGER) },
199 }
200 }
201}
202
203impl IntoR for Option<f64> {
204 type Error = std::convert::Infallible;
205 #[inline]
206 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
207 Ok(self.into_sexp())
208 }
209 #[inline]
210 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
211 Ok(unsafe { self.into_sexp_unchecked() })
212 }
213 #[inline]
214 fn into_sexp(self) -> crate::ffi::SEXP {
215 match self {
216 Some(v) => v.into_sexp(),
217 None => crate::ffi::SEXP::scalar_real(NA_REAL),
218 }
219 }
220 #[inline]
221 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
222 match self {
223 Some(v) => unsafe { v.into_sexp_unchecked() },
224 None => unsafe { crate::ffi::Rf_ScalarReal_unchecked(NA_REAL) },
225 }
226 }
227}
228
229impl IntoR for Option<crate::ffi::Rboolean> {
230 type Error = std::convert::Infallible;
231 #[inline]
232 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
233 Ok(self.into_sexp())
234 }
235 #[inline]
236 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
237 Ok(unsafe { self.into_sexp_unchecked() })
238 }
239 #[inline]
240 fn into_sexp(self) -> crate::ffi::SEXP {
241 match self {
242 Some(v) => crate::ffi::SEXP::scalar_logical_raw(v as i32),
244 None => crate::ffi::SEXP::scalar_logical_raw(NA_LOGICAL),
245 }
246 }
247 #[inline]
248 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
249 match self {
250 Some(v) => unsafe { crate::ffi::Rf_ScalarLogical_unchecked(v as i32) },
251 None => unsafe { crate::ffi::Rf_ScalarLogical_unchecked(NA_LOGICAL) },
252 }
253 }
254}
255
256impl IntoR for Option<crate::ffi::RLogical> {
257 type Error = std::convert::Infallible;
258 #[inline]
259 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
260 Ok(self.into_sexp())
261 }
262 #[inline]
263 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
264 Ok(unsafe { self.into_sexp_unchecked() })
265 }
266 #[inline]
267 fn into_sexp(self) -> crate::ffi::SEXP {
268 match self {
269 Some(v) => crate::ffi::SEXP::scalar_logical_raw(v.to_i32()),
270 None => crate::ffi::SEXP::scalar_logical_raw(NA_LOGICAL),
271 }
272 }
273 #[inline]
274 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
275 match self {
276 Some(v) => unsafe { crate::ffi::Rf_ScalarLogical_unchecked(v.to_i32()) },
277 None => unsafe { crate::ffi::Rf_ScalarLogical_unchecked(NA_LOGICAL) },
278 }
279 }
280}
281
282impl IntoR for Option<bool> {
283 type Error = std::convert::Infallible;
284 #[inline]
285 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
286 Ok(self.into_sexp())
287 }
288 #[inline]
289 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
290 Ok(unsafe { self.into_sexp_unchecked() })
291 }
292 #[inline]
293 fn into_sexp(self) -> crate::ffi::SEXP {
294 match self {
295 Some(v) => v.into_sexp(),
296 None => crate::ffi::SEXP::scalar_logical_raw(NA_LOGICAL),
297 }
298 }
299 #[inline]
300 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
301 match self {
302 Some(v) => unsafe { v.into_sexp_unchecked() },
303 None => unsafe { crate::ffi::Rf_ScalarLogical_unchecked(NA_LOGICAL) },
304 }
305 }
306}
307
308macro_rules! impl_option_smart_i64_into_r {
312 ($t:ty, $fits_i32:expr) => {
313 impl IntoR for Option<$t> {
314 type Error = std::convert::Infallible;
315 #[inline]
316 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
317 Ok(self.into_sexp())
318 }
319 #[inline]
320 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
321 self.try_into_sexp()
322 }
323 #[inline]
324 fn into_sexp(self) -> crate::ffi::SEXP {
325 match self {
326 Some(x) if $fits_i32(x) => (x as i32).into_sexp(),
327 Some(x) => (x as f64).into_sexp(),
328 None => crate::ffi::SEXP::scalar_integer(NA_INTEGER),
329 }
330 }
331 }
332 };
333}
334
335impl_option_smart_i64_into_r!(i64, |x: i64| x > i32::MIN as i64 && x <= i32::MAX as i64);
336impl_option_smart_i64_into_r!(u64, |x: u64| x <= i32::MAX as u64);
337impl_option_smart_i64_into_r!(isize, |x: isize| x > i32::MIN as isize
338 && x <= i32::MAX as isize);
339impl_option_smart_i64_into_r!(usize, |x: usize| x <= i32::MAX as usize);
340
341macro_rules! impl_option_coerce_into_r {
343 ($from:ty => $to:ty) => {
344 impl IntoR for Option<$from> {
345 type Error = std::convert::Infallible;
346 #[inline]
347 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
348 Ok(self.map(|x| x as $to).into_sexp())
349 }
350 #[inline]
351 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
352 self.try_into_sexp()
353 }
354 #[inline]
355 fn into_sexp(self) -> crate::ffi::SEXP {
356 self.map(|x| x as $to).into_sexp()
357 }
358 }
359 };
360}
361
362impl_option_coerce_into_r!(i8 => i32);
363impl_option_coerce_into_r!(i16 => i32);
364impl_option_coerce_into_r!(u16 => i32);
365impl_option_coerce_into_r!(u32 => i64); impl_option_coerce_into_r!(f32 => f64);
367
368impl<T: crate::externalptr::TypedExternal> IntoR for crate::externalptr::ExternalPtr<T> {
369 type Error = std::convert::Infallible;
370 #[inline]
371 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
372 Ok(self.as_sexp())
373 }
374 #[inline]
375 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
376 Ok(self.as_sexp())
377 }
378 #[inline]
379 fn into_sexp(self) -> crate::ffi::SEXP {
380 self.as_sexp()
381 }
382}
383
384impl<T: crate::externalptr::IntoExternalPtr> IntoR for T {
389 type Error = std::convert::Infallible;
390 #[inline]
391 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
392 Ok(self.into_sexp())
393 }
394 #[inline]
395 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
396 Ok(unsafe { self.into_sexp_unchecked() })
397 }
398 #[inline]
399 fn into_sexp(self) -> crate::ffi::SEXP {
400 crate::externalptr::ExternalPtr::new(self).into_sexp()
401 }
402 #[inline]
403 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
404 unsafe { crate::externalptr::ExternalPtr::new_unchecked(self).into_sexp() }
405 }
406}
407
408#[inline]
411pub(crate) fn str_to_charsxp(s: &str) -> crate::ffi::SEXP {
412 if s.is_empty() {
413 crate::ffi::SEXP::blank_string()
414 } else {
415 let _len: i32 = s.len().try_into().expect("string exceeds i32::MAX bytes");
416 crate::ffi::SEXP::charsxp(s)
417 }
418}
419
420#[inline]
422pub(crate) unsafe fn str_to_charsxp_unchecked(s: &str) -> crate::ffi::SEXP {
423 unsafe {
424 if s.is_empty() {
425 crate::ffi::SEXP::blank_string()
426 } else {
427 let len: i32 = s.len().try_into().expect("string exceeds i32::MAX bytes");
428 crate::ffi::Rf_mkCharLenCE_unchecked(s.as_ptr().cast(), len, crate::ffi::CE_UTF8)
429 }
430 }
431}
432
433impl IntoR for String {
434 type Error = crate::into_r_error::IntoRError;
435 #[inline]
436 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
437 self.as_str().try_into_sexp()
438 }
439 #[inline]
440 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
441 Ok(unsafe { self.into_sexp_unchecked() })
442 }
443 #[inline]
444 fn into_sexp(self) -> crate::ffi::SEXP {
445 self.as_str().into_sexp()
446 }
447 #[inline]
448 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
449 unsafe { self.as_str().into_sexp_unchecked() }
450 }
451}
452
453impl IntoR for char {
454 type Error = std::convert::Infallible;
455 #[inline]
456 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
457 Ok(self.into_sexp())
458 }
459 #[inline]
460 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
461 Ok(unsafe { self.into_sexp_unchecked() })
462 }
463 #[inline]
464 fn into_sexp(self) -> crate::ffi::SEXP {
465 let mut buf = [0u8; 4];
467 let s = self.encode_utf8(&mut buf);
468 crate::ffi::SEXP::scalar_string(str_to_charsxp(s))
469 }
470 #[inline]
471 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
472 let mut buf = [0u8; 4];
473 let s = self.encode_utf8(&mut buf);
474 unsafe { s.into_sexp_unchecked() }
475 }
476}
477
478impl IntoR for &str {
479 type Error = crate::into_r_error::IntoRError;
480 #[inline]
481 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
482 let _len = i32::try_from(self.len())
483 .map_err(|_| crate::into_r_error::IntoRError::StringTooLong { len: self.len() })?;
484 Ok(crate::ffi::SEXP::scalar_string(str_to_charsxp(self)))
485 }
486 #[inline]
487 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
488 Ok(unsafe { self.into_sexp_unchecked() })
489 }
490 #[inline]
491 fn into_sexp(self) -> crate::ffi::SEXP {
492 crate::ffi::SEXP::scalar_string(str_to_charsxp(self))
493 }
494 #[inline]
495 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
496 unsafe {
497 let charsxp = str_to_charsxp_unchecked(self);
498 crate::ffi::Rf_ScalarString_unchecked(charsxp)
499 }
500 }
501}
502
503impl IntoR for Option<&str> {
504 type Error = crate::into_r_error::IntoRError;
505 #[inline]
506 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
507 match self {
508 Some(s) => {
509 let _len = i32::try_from(s.len())
510 .map_err(|_| crate::into_r_error::IntoRError::StringTooLong { len: s.len() })?;
511 Ok(crate::ffi::SEXP::scalar_string(str_to_charsxp(s)))
512 }
513 None => Ok(crate::ffi::SEXP::scalar_string(
514 crate::ffi::SEXP::na_string(),
515 )),
516 }
517 }
518 #[inline]
519 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
520 Ok(unsafe { self.into_sexp_unchecked() })
521 }
522 #[inline]
523 fn into_sexp(self) -> crate::ffi::SEXP {
524 let charsxp = match self {
525 Some(s) => str_to_charsxp(s),
526 None => crate::ffi::SEXP::na_string(),
527 };
528 crate::ffi::SEXP::scalar_string(charsxp)
529 }
530 #[inline]
531 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
532 unsafe {
533 let charsxp = match self {
534 Some(s) => str_to_charsxp_unchecked(s),
535 None => crate::ffi::SEXP::na_string(),
536 };
537 crate::ffi::Rf_ScalarString_unchecked(charsxp)
538 }
539 }
540}
541
542impl IntoR for Option<String> {
543 type Error = crate::into_r_error::IntoRError;
544 #[inline]
545 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
546 self.as_deref().try_into_sexp()
547 }
548 #[inline]
549 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
550 Ok(unsafe { self.into_sexp_unchecked() })
551 }
552 #[inline]
553 fn into_sexp(self) -> crate::ffi::SEXP {
554 self.as_deref().into_sexp()
555 }
556 #[inline]
557 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
558 unsafe { self.as_deref().into_sexp_unchecked() }
559 }
560}
561
562impl<T> IntoR for Option<&T>
570where
571 T: Copy + IntoR,
572{
573 type Error = crate::into_r_error::IntoRError;
574 #[inline]
575 fn try_into_sexp(self) -> Result<crate::ffi::SEXP, Self::Error> {
576 match self {
577 Some(&v) => v
578 .try_into_sexp()
579 .map_err(|e| crate::into_r_error::IntoRError::Inner(e.to_string())),
580 None => Ok(crate::ffi::SEXP::nil()),
581 }
582 }
583 #[inline]
584 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::ffi::SEXP, Self::Error> {
585 Ok(unsafe { self.into_sexp_unchecked() })
586 }
587 #[inline]
588 fn into_sexp(self) -> crate::ffi::SEXP {
589 match self {
590 Some(&v) => v.into_sexp(),
591 None => crate::ffi::SEXP::nil(),
592 }
593 }
594 #[inline]
595 unsafe fn into_sexp_unchecked(self) -> crate::ffi::SEXP {
596 match self {
597 Some(&v) => unsafe { v.into_sexp_unchecked() },
598 None => crate::ffi::SEXP::nil(),
599 }
600 }
601}
602
603