aorist_extendr_api/robj/
into_robj.rs1use super::*;
2use crate::single_threaded;
3use std::collections::HashMap;
4
5pub(crate) fn str_to_character(s: &str) -> SEXP {
6 unsafe {
7 if s.is_na() {
8 R_NaString
9 } else {
10 Rf_mkCharLen(s.as_ptr() as *const raw::c_char, s.len() as i32)
11 }
12 }
13}
14
15impl From<()> for Robj {
17 fn from(_: ()) -> Self {
18 unsafe { Robj::Sys(R_NilValue) }
20 }
21}
22
23impl<T> From<Result<T>> for Robj
38where
39 T: Into<Robj>,
40{
41 fn from(res: Result<T>) -> Self {
42 res.unwrap().into()
44 }
45}
46
47impl From<&Robj> for Robj {
49 fn from(val: &Robj) -> Self {
52 unsafe { new_owned(val.get()) }
53 }
54}
55
56pub trait IntoRobj {
57 fn into_robj(self) -> Robj;
58}
59
60impl<T> IntoRobj for T
61where
62 Robj: From<T>,
63{
64 fn into_robj(self) -> Robj {
65 self.into()
66 }
67}
68
69pub trait ToVectorValue {
73 fn sexptype() -> SEXPTYPE {
74 0
75 }
76
77 fn to_real(&self) -> f64
78 where
79 Self: Sized,
80 {
81 0.
82 }
83
84 fn to_integer(&self) -> i32
85 where
86 Self: Sized,
87 {
88 std::i32::MIN
89 }
90
91 fn to_logical(&self) -> i32
92 where
93 Self: Sized,
94 {
95 std::i32::MIN
96 }
97
98 fn to_raw(&self) -> u8
99 where
100 Self: Sized,
101 {
102 0
103 }
104
105 fn to_sexp(&self) -> SEXP
106 where
107 Self: Sized,
108 {
109 unsafe { R_NilValue }
110 }
111}
112
113macro_rules! impl_real_tvv {
114 ($t: ty) => {
115 impl ToVectorValue for $t {
116 fn sexptype() -> SEXPTYPE {
117 REALSXP
118 }
119
120 fn to_real(&self) -> f64 {
121 *self as f64
122 }
123 }
124
125 impl ToVectorValue for &$t {
126 fn sexptype() -> SEXPTYPE {
127 REALSXP
128 }
129
130 fn to_real(&self) -> f64 {
131 **self as f64
132 }
133 }
134
135 impl ToVectorValue for Option<$t> {
136 fn sexptype() -> SEXPTYPE {
137 REALSXP
138 }
139
140 fn to_real(&self) -> f64 {
141 if self.is_some() {
142 self.unwrap() as f64
143 } else {
144 unsafe { R_NaReal }
145 }
146 }
147 }
148 };
149}
150
151impl_real_tvv!(f64);
152impl_real_tvv!(f32);
153impl_real_tvv!(usize);
154
155macro_rules! impl_integer_tvv {
156 ($t: ty) => {
157 impl ToVectorValue for $t {
158 fn sexptype() -> SEXPTYPE {
159 INTSXP
160 }
161
162 fn to_integer(&self) -> i32 {
163 *self as i32
164 }
165 }
166
167 impl ToVectorValue for &$t {
168 fn sexptype() -> SEXPTYPE {
169 INTSXP
170 }
171
172 fn to_integer(&self) -> i32 {
173 **self as i32
174 }
175 }
176
177 impl ToVectorValue for Option<$t> {
178 fn sexptype() -> SEXPTYPE {
179 INTSXP
180 }
181
182 fn to_integer(&self) -> i32 {
183 if self.is_some() {
184 self.unwrap() as i32
185 } else {
186 unsafe { R_NaInt }
187 }
188 }
189 }
190 };
191}
192
193impl_integer_tvv!(i8);
194impl_integer_tvv!(i16);
195impl_integer_tvv!(i32);
196impl_integer_tvv!(i64);
197impl_integer_tvv!(u8);
198impl_integer_tvv!(u16);
199impl_integer_tvv!(u32);
200impl_integer_tvv!(u64);
201
202macro_rules! impl_str_tvv {
203 ($t: ty) => {
204 impl ToVectorValue for $t {
205 fn sexptype() -> SEXPTYPE {
206 STRSXP
207 }
208
209 fn to_sexp(&self) -> SEXP
210 where
211 Self: Sized,
212 {
213 str_to_character(self.as_ref())
214 }
215 }
216
217 impl ToVectorValue for &$t {
218 fn sexptype() -> SEXPTYPE {
219 STRSXP
220 }
221
222 fn to_sexp(&self) -> SEXP
223 where
224 Self: Sized,
225 {
226 str_to_character(self.as_ref())
227 }
228 }
229
230 impl ToVectorValue for Option<$t> {
231 fn sexptype() -> SEXPTYPE {
232 STRSXP
233 }
234
235 fn to_sexp(&self) -> SEXP
236 where
237 Self: Sized,
238 {
239 if let Some(s) = self {
240 str_to_character(s.as_ref())
241 } else {
242 unsafe { R_NaString }
243 }
244 }
245 }
246 };
247}
248
249impl_str_tvv! {&str}
250impl_str_tvv! {String}
251
252impl ToVectorValue for bool {
253 fn sexptype() -> SEXPTYPE {
254 LGLSXP
255 }
256
257 fn to_logical(&self) -> i32
258 where
259 Self: Sized,
260 {
261 *self as i32
262 }
263}
264
265impl ToVectorValue for &bool {
266 fn sexptype() -> SEXPTYPE {
267 LGLSXP
268 }
269
270 fn to_logical(&self) -> i32
271 where
272 Self: Sized,
273 {
274 **self as i32
275 }
276}
277
278impl ToVectorValue for Bool {
279 fn sexptype() -> SEXPTYPE {
280 LGLSXP
281 }
282
283 fn to_logical(&self) -> i32
284 where
285 Self: Sized,
286 {
287 self.0
288 }
289}
290
291impl ToVectorValue for &Bool {
292 fn sexptype() -> SEXPTYPE {
293 LGLSXP
294 }
295
296 fn to_logical(&self) -> i32
297 where
298 Self: Sized,
299 {
300 self.0
301 }
302}
303
304impl ToVectorValue for Option<bool> {
305 fn sexptype() -> SEXPTYPE {
306 LGLSXP
307 }
308
309 fn to_logical(&self) -> i32 {
310 if self.is_some() {
311 self.unwrap() as i32
312 } else {
313 unsafe { R_NaInt }
314 }
315 }
316}
317
318fn fixed_size_collect<I>(iter: I, len: usize) -> Robj
320where
321 I: Iterator,
322 I: Sized,
323 I::Item: ToVectorValue,
324{
325 single_threaded(|| unsafe {
326 let sexptype = I::Item::sexptype();
328 if sexptype != 0 {
329 let sexp = Rf_allocVector(sexptype, len as R_xlen_t);
330 ownership::protect(sexp);
331 match sexptype {
332 REALSXP => {
333 let ptr = REAL(sexp);
334 for (i, v) in iter.enumerate() {
335 *ptr.add(i) = v.to_real();
336 }
337 }
338 INTSXP => {
339 let ptr = INTEGER(sexp);
340 for (i, v) in iter.enumerate() {
341 *ptr.add(i) = v.to_integer();
342 }
343 }
344 LGLSXP => {
345 let ptr = LOGICAL(sexp);
346 for (i, v) in iter.enumerate() {
347 *ptr.add(i) = v.to_logical();
348 }
349 }
350 STRSXP => {
351 for (i, v) in iter.enumerate() {
352 SET_STRING_ELT(sexp, i as isize, v.to_sexp());
353 }
354 }
355 _ => {
356 panic!("unexpected SEXPTYPE in collect_robj");
357 }
358 }
359 Robj::Owned(sexp)
360 } else {
361 Robj::from(())
362 }
363 })
364}
365
366pub trait RobjItertools: Iterator {
368 fn collect_robj(self) -> Robj
391 where
392 Self: Iterator,
393 Self: Sized,
394 Self::Item: ToVectorValue,
395 {
396 if let (len, Some(max)) = self.size_hint() {
397 if len == max {
398 return fixed_size_collect(self, len);
399 }
400 }
401 let vec: Vec<_> = self.collect();
403 assert!(vec.iter().size_hint() == (vec.len(), Some(vec.len())));
404 vec.into_iter().collect_robj()
405 }
406}
407
408impl<T> RobjItertools for T where T: Iterator {}
410
411impl<T> From<T> for Robj
413where
414 T: ToVectorValue,
415{
416 fn from(scalar: T) -> Self {
417 Some(scalar).into_iter().collect_robj()
418 }
419}
420
421macro_rules! impl_from_iter {
424 ($t: ty) => {
425 impl<'a, T> From<$t> for Robj
426 where
427 Self: 'a,
428 T: Clone + 'a,
429 T: ToVectorValue,
430 {
431 fn from(val: $t) -> Self {
432 val.iter().cloned().collect_robj()
433 }
434 }
435 };
436}
437
438macro_rules! impl_from_into_iter {
439 ($t: ty) => {
440 impl<'a, T> From<$t> for Robj
441 where
442 Self: 'a,
443 T: 'a,
444 &'a T: ToVectorValue,
445 {
446 fn from(val: $t) -> Self {
447 val.into_iter().collect_robj()
448 }
449 }
450 };
451}
452
453macro_rules! impl_from_as_iterator {
454 ($t: ty) => {
455 impl<T> From<$t> for Robj
456 where
457 $t: RobjItertools,
458 <$t as Iterator>::Item: ToVectorValue,
459 T: ToVectorValue,
460 {
461 fn from(val: $t) -> Self {
462 val.collect_robj()
463 }
464 }
465 };
466}
467
468impl_from_iter! {[T; 1]}
481impl_from_iter! {[T; 2]}
482impl_from_iter! {[T; 3]}
483impl_from_iter! {[T; 4]}
484impl_from_iter! {[T; 5]}
485impl_from_iter! {[T; 6]}
486impl_from_iter! {[T; 7]}
487impl_from_iter! {[T; 8]}
488impl_from_iter! {[T; 9]}
489impl_from_iter! {[T; 10]}
490impl_from_iter! {[T; 11]}
491impl_from_iter! {[T; 12]}
492impl_from_iter! {[T; 13]}
493impl_from_iter! {[T; 14]}
494impl_from_iter! {[T; 15]}
495impl_from_iter! {[T; 16]}
496impl_from_iter! {[T; 17]}
497impl_from_iter! {[T; 18]}
498impl_from_iter! {[T; 19]}
499impl_from_iter! {Vec<T>}
500
501impl_from_into_iter! {&'a [T]}
502
503impl_from_as_iterator! {Range<T>}
504impl_from_as_iterator! {RangeInclusive<T>}
505
506impl From<Real> for Robj {
507 fn from(val: Real) -> Self {
509 val.collect_robj()
510 }
511}
512
513impl From<Int> for Robj {
514 fn from(val: Int) -> Self {
516 val.collect_robj()
517 }
518}
519
520impl From<Logical> for Robj {
521 fn from(val: Logical) -> Self {
523 val.collect_robj()
524 }
525}
526
527impl<'a> From<HashMap<&'a str, Robj>> for Robj {
528 fn from(val: HashMap<&'a str, Robj>) -> Self {
530 let res: Robj = List::from_values(val.iter().map(|(_, v)| v)).into();
531 res.set_names(val.into_iter().map(|(k, _)| k)).unwrap()
532 }
533}
534
535impl<'a> From<Vec<Robj>> for Robj {
536 fn from(val: Vec<Robj>) -> Self {
538 List::from_values(val.iter()).into()
539 }
540}