extendr_api/wrapper/
wrapper_macros.rs1use super::*;
2use extendr_ffi::{R_xlen_t, SET_VECTOR_ELT};
3
4pub(crate) fn make_symbol(name: &str) -> SEXP {
5 let name = std::ffi::CString::new(name).unwrap();
6 unsafe { extendr_ffi::Rf_install(name.as_ptr()) }
7}
8
9pub(crate) fn make_vector<T>(sexptype: SEXPTYPE, values: T) -> Robj
10where
11 T: IntoIterator,
12 T::IntoIter: ExactSizeIterator,
13 T::Item: Into<Robj>,
14{
15 single_threaded(|| unsafe {
16 let values = values.into_iter();
17 let mut res = Robj::alloc_vector(sexptype, values.len());
18 let sexp = res.get_mut();
19 for (i, val) in values.enumerate() {
20 SET_VECTOR_ELT(sexp, i as R_xlen_t, val.into().get());
21 }
22 res
23 })
24}
25
26macro_rules! make_conversions {
27 ($typename: ident, $errname: ident, $isfunc: ident, $errstr: expr) => {
28 impl From<$typename> for Robj {
29 fn from(val: $typename) -> Self {
31 val.robj
32 }
33 }
34
35 impl From<&$typename> for Robj {
37 fn from(val: &$typename) -> Self {
39 val.robj.to_owned()
40 }
41 }
42
43 impl TryFrom<&Robj> for $typename {
44 type Error = crate::Error;
45
46 fn try_from(robj: &Robj) -> Result<Self> {
48 if robj.$isfunc() {
49 Ok($typename { robj: robj.clone() })
50 } else {
51 Err(Error::$errname(robj.clone()))
52 }
53 }
54 }
55
56 impl TryFrom<Robj> for $typename {
57 type Error = crate::Error;
58
59 fn try_from(robj: Robj) -> Result<Self> {
61 <$typename>::try_from(&robj)
62 }
63 }
64
65 impl TryFrom<&Robj> for Option<$typename> {
66 type Error = crate::Error;
67
68 fn try_from(robj: &Robj) -> Result<Self> {
70 if robj.is_null() {
71 Ok(None)
72 } else {
73 Ok(Some(<$typename>::try_from(robj)?))
74 }
75 }
76 }
77
78 impl TryFrom<Robj> for Option<$typename> {
79 type Error = crate::Error;
80
81 fn try_from(robj: Robj) -> Result<Self> {
83 <Option<$typename>>::try_from(&robj)
84 }
85 }
86
87 make_getsexp!($typename, impl);
88 };
89}
90
91macro_rules! make_getsexp {
92 ($typename: ty, $($impl : tt)*) => {
93 $($impl)* GetSexp for $typename {
94 unsafe fn get(&self) -> SEXP {
95 self.robj.get()
96 }
97
98 unsafe fn get_mut(&mut self) -> SEXP {
99 self.robj.get_mut()
100 }
101
102 fn as_robj(&self) -> &Robj {
103 &self.robj
104 }
105
106 fn as_robj_mut(&mut self) -> &mut Robj {
107 &mut self.robj
108 }
109 }
110
111 $($impl)* Length for $typename {}
115
116 $($impl)* Types for $typename {}
118
119 $($impl)* Conversions for $typename {}
121
122 $($impl)* Rinternals for $typename {}
124
125 $($impl)* Slices for $typename {}
127
128 $($impl)* Operators for $typename {}
130 };
131}
132
133make_conversions!(Pairlist, ExpectedPairlist, is_pairlist, "Not a pairlist");
134
135make_conversions!(
136 Function,
137 ExpectedFunction,
138 is_function,
139 "Not a function or primitive."
140);
141
142make_conversions!(Raw, ExpectedRaw, is_raw, "Not a raw object");
143
144make_conversions!(
145 Environment,
146 ExpectedEnvironment,
147 is_environment,
148 "Not an Environment"
149);
150
151make_conversions!(List, ExpectedList, is_list, "Not a List");
152
153make_conversions!(
154 Expressions,
155 ExpectedExpression,
156 is_expressions,
157 "Not an Expression"
158);
159
160make_conversions!(
161 Language,
162 ExpectedLanguage,
163 is_language,
164 "Not a Language object"
165);
166
167make_conversions!(Symbol, ExpectedSymbol, is_symbol, "Not a Symbol object");
168
169make_conversions!(
170 Primitive,
171 ExpectedPrimitive,
172 is_primitive,
173 "Not a Primitive object"
174);
175
176make_conversions!(Promise, ExpectedPromise, is_promise, "Not a Promise object");
177
178make_conversions!(Altrep, ExpectedAltrep, is_altrep, "Not an Altrep type");
179
180make_conversions!(S4, ExpectedS4, is_s4, "Not a S4 type");
181
182make_conversions!(Integers, ExpectedInteger, is_integer, "Not an integer type");
183make_conversions!(Logicals, ExpectedLogical, is_logical, "Not a logical type");
184make_conversions!(Doubles, ExpectedReal, is_real, "Not a floating point type");
185make_conversions!(
186 Complexes,
187 ExpectedComplex,
188 is_complex,
189 "Not a complex number or vector"
190);
191make_conversions!(Strings, ExpectedString, is_string, "Not a string vector");
194
195make_getsexp!(Dataframe<T>, impl<T>);
196
197pub trait Conversions: GetSexp {
206 fn as_symbol(&self) -> Option<Symbol> {
215 Symbol::try_from(self.as_robj()).ok()
216 }
217
218 fn as_char(&self) -> Option<Rstr> {
227 Rstr::try_from(self.as_robj()).ok()
228 }
229
230 fn as_raw(&self) -> Option<Raw> {
240 Raw::try_from(self.as_robj()).ok()
241 }
242
243 fn as_language(&self) -> Option<Language> {
253 Language::try_from(self.as_robj()).ok()
254 }
255
256 fn as_pairlist(&self) -> Option<Pairlist> {
267 Pairlist::try_from(self.as_robj()).ok()
268 }
269
270 fn as_list(&self) -> Option<List> {
279 List::try_from(self.as_robj()).ok()
280 }
281
282 fn as_expressions(&self) -> Option<Expressions> {
292 Expressions::try_from(self.as_robj()).ok()
293 }
294
295 fn as_environment(&self) -> Option<Environment> {
308 Environment::try_from(self.as_robj()).ok()
309 }
310
311 fn as_function(&self) -> Option<Function> {
320 Function::try_from(self.as_robj()).ok()
321 }
322
323 fn as_promise(&self) -> Option<Promise> {
325 Promise::try_from(self.as_robj()).ok()
326 }
327}
328
329impl Conversions for Robj {}
330
331pub trait SymPair {
332 fn sym_pair(self) -> (Option<Robj>, Robj);
333}
334
335impl<S, R> SymPair for (S, R)
336where
337 S: AsRef<str>,
338 R: Into<Robj>,
339{
340 fn sym_pair(self) -> (Option<Robj>, Robj) {
341 let val = self.0.as_ref();
342 let nm = if val.is_empty() {
344 None
345 } else {
346 Some(r!(Symbol::from_string(val)))
347 };
348 (nm, self.1.into())
349 }
350}
351
352impl<S, R> SymPair for &(S, R)
353where
354 S: AsRef<str>,
355 R: Into<Robj>,
356 R: Clone,
357{
358 fn sym_pair(self) -> (Option<Robj>, Robj) {
359 let val = self.0.as_ref();
360 let nm = if val.is_empty() {
361 None
362 } else {
363 Some(r!(Symbol::from_string(val)))
364 };
365 (nm, self.1.clone().into())
366 }
367}