extendr_api/wrapper/
wrapper_macros.rs1use 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!(
124 Environment,
125 ExpectedEnvironment,
126 is_environment,
127 "Not an Environment"
128);
129
130make_conversions!(List, ExpectedList, is_list, "Not a List");
131
132make_conversions!(
133 Expressions,
134 ExpectedExpression,
135 is_expressions,
136 "Not an Expression"
137);
138
139make_conversions!(
140 Language,
141 ExpectedLanguage,
142 is_language,
143 "Not a Language object"
144);
145
146make_conversions!(Symbol, ExpectedSymbol, is_symbol, "Not a Symbol object");
147
148make_conversions!(
149 Primitive,
150 ExpectedPrimitive,
151 is_primitive,
152 "Not a Primitive object"
153);
154
155make_conversions!(Promise, ExpectedPromise, is_promise, "Not a Promise object");
156
157make_conversions!(Altrep, ExpectedAltrep, is_altrep, "Not an Altrep type");
158
159make_conversions!(S4, ExpectedS4, is_s4, "Not a S4 type");
160
161make_conversions!(Integers, ExpectedInteger, is_integer, "Not an integer type");
162make_conversions!(Logicals, ExpectedLogical, is_logical, "Not a logical type");
163make_conversions!(Doubles, ExpectedReal, is_real, "Not a floating point type");
164make_conversions!(
165 Complexes,
166 ExpectedComplex,
167 is_complex,
168 "Not a complex number or vector"
169);
170make_conversions!(Strings, ExpectedString, is_string, "Not a string vector");
173
174make_getsexp!(Dataframe<T>, impl<T>);
175
176pub trait Conversions: GetSexp {
185 fn as_symbol(&self) -> Option<Symbol> {
194 Symbol::try_from(self.as_robj()).ok()
195 }
196
197 fn as_char(&self) -> Option<Rstr> {
206 Rstr::try_from(self.as_robj()).ok()
207 }
208
209 fn as_raw(&self) -> Option<Raw> {
219 Raw::try_from(self.as_robj()).ok()
220 }
221
222 fn as_language(&self) -> Option<Language> {
232 Language::try_from(self.as_robj()).ok()
233 }
234
235 fn as_pairlist(&self) -> Option<Pairlist> {
246 Pairlist::try_from(self.as_robj()).ok()
247 }
248
249 fn as_list(&self) -> Option<List> {
258 List::try_from(self.as_robj()).ok()
259 }
260
261 fn as_expressions(&self) -> Option<Expressions> {
271 Expressions::try_from(self.as_robj()).ok()
272 }
273
274 fn as_environment(&self) -> Option<Environment> {
287 Environment::try_from(self.as_robj()).ok()
288 }
289
290 fn as_function(&self) -> Option<Function> {
299 Function::try_from(self.as_robj()).ok()
300 }
301
302 fn as_promise(&self) -> Option<Promise> {
304 Promise::try_from(self.as_robj()).ok()
305 }
306}
307
308impl Conversions for Robj {}
309
310pub trait SymPair {
311 fn sym_pair(self) -> (Option<Robj>, Robj);
312}
313
314impl<S, R> SymPair for (S, R)
315where
316 S: AsRef<str>,
317 R: Into<Robj>,
318{
319 fn sym_pair(self) -> (Option<Robj>, Robj) {
320 let val = self.0.as_ref();
321 let nm = if val.is_empty() {
323 None
324 } else {
325 Some(r!(Symbol::from_string(val)))
326 };
327 (nm, self.1.into())
328 }
329}
330
331impl<S, R> SymPair for &(S, R)
332where
333 S: AsRef<str>,
334 R: Into<Robj>,
335 R: Clone,
336{
337 fn sym_pair(self) -> (Option<Robj>, Robj) {
338 use crate as extendr_api;
339 let val = self.0.as_ref();
340 let nm = if val.is_empty() {
341 None
342 } else {
343 Some(r!(Symbol::from_string(val)))
344 };
345 (nm, self.1.clone().into())
346 }
347}