extendr_api/wrapper/
wrapper_macros.rs
1use super::*;
2use crate as extendr_api;
3use extendr_ffi::{R_xlen_t, SET_VECTOR_ELT};
4
5pub(crate) fn make_symbol(name: &str) -> SEXP {
6 let name = CString::new(name).unwrap();
7 unsafe { extendr_ffi::Rf_install(name.as_ptr()) }
8}
9
10pub(crate) fn make_vector<T>(sexptype: SEXPTYPE, values: T) -> Robj
11where
12 T: IntoIterator,
13 T::IntoIter: ExactSizeIterator,
14 T::Item: Into<Robj>,
15{
16 single_threaded(|| unsafe {
17 let values = values.into_iter();
18 let mut res = Robj::alloc_vector(sexptype, values.len());
19 let sexp = res.get_mut();
20 for (i, val) in values.enumerate() {
21 SET_VECTOR_ELT(sexp, i as R_xlen_t, val.into().get());
22 }
23 res
24 })
25}
26
27macro_rules! make_conversions {
28 ($typename: ident, $errname: ident, $isfunc: ident, $errstr: expr) => {
29 impl From<$typename> for Robj {
30 fn from(val: $typename) -> Self {
32 val.robj
33 }
34 }
35
36 impl From<&$typename> for Robj {
38 fn from(val: &$typename) -> Self {
40 val.robj.to_owned()
41 }
42 }
43
44 impl TryFrom<&Robj> for $typename {
45 type Error = crate::Error;
46
47 fn try_from(robj: &Robj) -> Result<Self> {
49 if robj.$isfunc() {
50 Ok($typename { robj: robj.clone() })
51 } else {
52 Err(Error::$errname(robj.clone()))
53 }
54 }
55 }
56
57 impl TryFrom<Robj> for $typename {
58 type Error = crate::Error;
59
60 fn try_from(robj: Robj) -> Result<Self> {
62 <$typename>::try_from(&robj)
63 }
64 }
65
66 make_getsexp!($typename, impl);
67 };
68}
69
70macro_rules! make_getsexp {
71 ($typename: ty, $($impl : tt)*) => {
72 $($impl)* GetSexp for $typename {
73 unsafe fn get(&self) -> SEXP {
74 self.robj.get()
75 }
76
77 unsafe fn get_mut(&mut self) -> SEXP {
78 self.robj.get_mut()
79 }
80
81 fn as_robj(&self) -> &Robj {
82 &self.robj
83 }
84
85 fn as_robj_mut(&mut self) -> &mut Robj {
86 &mut self.robj
87 }
88 }
89
90 $($impl)* Length for $typename {}
94
95 $($impl)* Types for $typename {}
97
98 $($impl)* Conversions for $typename {}
100
101 $($impl)* Rinternals for $typename {}
103
104 $($impl)* Slices for $typename {}
106
107 $($impl)* Operators for $typename {}
109 };
110}
111
112make_conversions!(Pairlist, ExpectedPairlist, is_pairlist, "Not a pairlist");
113
114make_conversions!(
115 Function,
116 ExpectedFunction,
117 is_function,
118 "Not a function or primitive."
119);
120
121make_conversions!(Raw, ExpectedRaw, is_raw, "Not a raw object");
122
123make_conversions!(Rstr, ExpectedRstr, is_char, "Not a character object");
124
125make_conversions!(
126 Environment,
127 ExpectedEnvironment,
128 is_environment,
129 "Not an Environment"
130);
131
132make_conversions!(List, ExpectedList, is_list, "Not a List");
133
134make_conversions!(
135 Expressions,
136 ExpectedExpression,
137 is_expressions,
138 "Not an Expression"
139);
140
141make_conversions!(
142 Language,
143 ExpectedLanguage,
144 is_language,
145 "Not a Language object"
146);
147
148make_conversions!(Symbol, ExpectedSymbol, is_symbol, "Not a Symbol object");
149
150make_conversions!(
151 Primitive,
152 ExpectedPrimitive,
153 is_primitive,
154 "Not a Primitive object"
155);
156
157make_conversions!(Promise, ExpectedPromise, is_promise, "Not a Promise object");
158
159make_conversions!(Altrep, ExpectedAltrep, is_altrep, "Not an Altrep type");
160
161make_conversions!(S4, ExpectedS4, is_s4, "Not a S4 type");
162
163make_conversions!(Integers, ExpectedInteger, is_integer, "Not an integer type");
164make_conversions!(Logicals, ExpectedLogical, is_logical, "Not a logical type");
165make_conversions!(Doubles, ExpectedReal, is_real, "Not a floating point type");
166make_conversions!(
167 Complexes,
168 ExpectedComplex,
169 is_complex,
170 "Not a complex number or vector"
171);
172make_conversions!(Strings, ExpectedString, is_string, "Not a string vector");
175
176make_getsexp!(Dataframe<T>, impl<T>);
177
178pub trait Conversions: GetSexp {
187 fn as_symbol(&self) -> Option<Symbol> {
196 Symbol::try_from(self.as_robj()).ok()
197 }
198
199 fn as_char(&self) -> Option<Rstr> {
208 Rstr::try_from(self.as_robj()).ok()
209 }
210
211 fn as_raw(&self) -> Option<Raw> {
221 Raw::try_from(self.as_robj()).ok()
222 }
223
224 fn as_language(&self) -> Option<Language> {
234 Language::try_from(self.as_robj()).ok()
235 }
236
237 fn as_pairlist(&self) -> Option<Pairlist> {
248 Pairlist::try_from(self.as_robj()).ok()
249 }
250
251 fn as_list(&self) -> Option<List> {
260 List::try_from(self.as_robj()).ok()
261 }
262
263 fn as_expressions(&self) -> Option<Expressions> {
273 Expressions::try_from(self.as_robj()).ok()
274 }
275
276 fn as_environment(&self) -> Option<Environment> {
289 Environment::try_from(self.as_robj()).ok()
290 }
291
292 fn as_function(&self) -> Option<Function> {
301 Function::try_from(self.as_robj()).ok()
302 }
303
304 fn as_promise(&self) -> Option<Promise> {
306 Promise::try_from(self.as_robj()).ok()
307 }
308}
309
310impl Conversions for Robj {}
311
312pub trait SymPair {
313 fn sym_pair(self) -> (Option<Robj>, Robj);
314}
315
316impl<S, R> SymPair for (S, R)
317where
318 S: AsRef<str>,
319 R: Into<Robj>,
320{
321 fn sym_pair(self) -> (Option<Robj>, Robj) {
322 let val = self.0.as_ref();
323 let nm = if val.is_empty() {
325 None
326 } else {
327 Some(r!(Symbol::from_string(val)))
328 };
329 (nm, self.1.into())
330 }
331}
332
333impl<S, R> SymPair for &(S, R)
334where
335 S: AsRef<str>,
336 R: Into<Robj>,
337 R: Clone,
338{
339 fn sym_pair(self) -> (Option<Robj>, Robj) {
340 use crate as extendr_api;
341 let val = self.0.as_ref();
342 let nm = if val.is_empty() {
343 None
344 } else {
345 Some(r!(Symbol::from_string(val)))
346 };
347 (nm, self.1.clone().into())
348 }
349}