Skip to main content

aorist_extendr_api/robj/
mod.rs

1//! R object handling.
2//!
3//! See. <https://cran.r-project.org/doc/manuals/R-exts.html>
4//!
5//! Fundamental principals:
6//!
7//! * Any function that can break the protection mechanism is unsafe.
8//! * Users should be able to do almost everything without using libR_sys.
9//! * The interface should be friendly to R users without Rust experience.
10//!
11
12use libR_sys::*;
13use std::os::raw;
14
15use crate::*;
16
17use std::collections::HashMap;
18use std::iter::IntoIterator;
19use std::ops::{Range, RangeInclusive};
20
21// deprecated
22mod from_robj;
23
24mod into_robj;
25mod operators;
26mod rinternals;
27mod try_from_robj;
28
29#[cfg(test)]
30mod tests;
31
32pub use from_robj::*;
33pub use into_robj::*;
34pub use iter::*;
35pub use operators::*;
36pub use rinternals::*;
37
38/// Wrapper for an R S-expression pointer (SEXP).
39///
40/// Create R objects from rust types and iterators:
41///
42/// ```
43/// use extendr_api::prelude::*;
44/// test! {
45///     // Different ways of making integer scalar 1.
46///     let non_na : Option<i32> = Some(1);
47///     let a : Robj = vec![1].into();
48///     let b = r!(1);
49///     let c = r!(vec![1]);
50///     let d = r!(non_na);
51///     let e = r!([1]);
52///     assert_eq!(a, b);
53///     assert_eq!(a, c);
54///     assert_eq!(a, d);
55///     assert_eq!(a, e);
56///
57///     // Different ways of making boolean scalar TRUE.
58///     let a : Robj = true.into();
59///     let b = r!(TRUE);
60///     assert_eq!(a, b);
61///
62///     // Create a named list
63///     let a = list!(a = 1, b = "x");
64///     assert_eq!(a.len(), 2);
65///
66///     // Use an iterator (like 1:10)
67///     let a = r!(1 ..= 10);
68///     assert_eq!(a, r!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]));
69///
70///     // Use an iterator (like (1:10)[(1:10) %% 3 == 0])
71///     let a = (1 ..= 10).filter(|v| v % 3 == 0).collect_robj();
72///     assert_eq!(a, r!([3, 6, 9]));
73/// }
74/// ```
75///
76/// Use iterators to get the contents of R objects.
77///
78/// ```
79/// use extendr_api::prelude::*;
80/// test! {
81///     let a : Robj = r!([1, 2, 3, 4, 5]);
82///     let iter = a.as_integer_iter().unwrap();
83///     let robj = iter.filter(|&x| x < 3).collect_robj();
84///     assert_eq!(robj, r!([1, 2]));
85/// }
86/// ```
87///
88/// Convert to/from Rust vectors.
89///
90/// ```
91/// use extendr_api::prelude::*;
92/// test! {
93///     let a : Robj = r!(vec![1., 2., 3., 4.]);
94///     let b : Vec<f64> = a.as_real_vector().unwrap();
95///     assert_eq!(a.len(), 4);
96///     assert_eq!(b, vec![1., 2., 3., 4.]);
97/// }
98/// ```
99///
100/// Iterate over names and values.
101///
102/// ```
103/// use extendr_api::prelude::*;
104/// test! {
105///     let abc = list!(a = 1, b = "x", c = vec![1, 2]);
106///     let names : Vec<_> = abc.names().unwrap().collect();
107///     let names_and_values : Vec<_> = abc.as_list().unwrap().iter().collect();
108///     assert_eq!(names, vec!["a", "b", "c"]);
109///     assert_eq!(names_and_values, vec![("a", r!(1)), ("b", r!("x")), ("c", r!(vec![1, 2]))]);
110/// }
111/// ```
112///
113/// NOTE: as much as possible we wish to make this object safe (ie. no segfaults).
114///
115/// If you avoid using unsafe functions it is more likely that you will avoid
116/// panics and segfaults. We will take great trouble to ensure that this
117/// is true.
118///
119pub enum Robj {
120    // This object owns the SEXP and must free it.
121    #[doc(hidden)]
122    Owned(SEXP),
123
124    //  This object references a SEXP owned by libR.
125    #[doc(hidden)]
126    Sys(SEXP),
127}
128
129impl Clone for Robj {
130    fn clone(&self) -> Self {
131        unsafe {
132            match *self {
133                Robj::Owned(sexp) => new_owned(sexp),
134                Robj::Sys(sexp) => new_sys(sexp),
135            }
136        }
137    }
138}
139
140impl Default for Robj {
141    fn default() -> Self {
142        Robj::from(())
143    }
144}
145
146impl Robj {
147    /// Get a copy of the underlying SEXP.
148    /// Note: this is unsafe.
149    #[doc(hidden)]
150    pub unsafe fn get(&self) -> SEXP {
151        match self {
152            Robj::Owned(sexp) => *sexp,
153            Robj::Sys(sexp) => *sexp,
154        }
155    }
156
157    /// Get a copy of the underlying SEXP for mutable types.
158    /// This is valid only for owned objects as we are not
159    /// permitted to modify parameters or system objects.
160    #[doc(hidden)]
161    pub unsafe fn get_mut(&mut self) -> Option<SEXP> {
162        match self {
163            Robj::Owned(sexp) => Some(*sexp),
164            Robj::Sys(_) => None,
165        }
166    }
167
168    #[doc(hidden)]
169    /// Get the XXXSXP type of the object.
170    pub fn sexptype(&self) -> u32 {
171        unsafe { TYPEOF(self.get()) as u32 }
172    }
173
174    /// Get the type of an R object.
175    /// ```
176    /// use extendr_api::prelude::*;
177    /// test! {
178    ///     assert_eq!(r!(NULL).rtype(), RType::Null);
179    ///     assert_eq!(sym!(xyz).rtype(), RType::Symbol);
180    ///     assert_eq!(r!(Pairlist::from_pairs(vec![("a", r!(1))])).rtype(), RType::Pairlist);
181    ///     assert_eq!(R!("function() {}")?.rtype(), RType::Function);
182    ///     assert_eq!(Environment::new_with_parent(global_env()).rtype(), RType::Environment);
183    ///     assert_eq!(lang!("+", 1, 2).rtype(), RType::Language);
184    ///     assert_eq!(r!(Primitive::from_string("if")).rtype(), RType::Special);
185    ///     assert_eq!(r!(Primitive::from_string("+")).rtype(), RType::Builtin);
186    ///     assert_eq!(r!(Character::from_string("hello")).rtype(), RType::Character);
187    ///     assert_eq!(r!(TRUE).rtype(), RType::Logical);
188    ///     assert_eq!(r!(1).rtype(), RType::Integer);
189    ///     assert_eq!(r!(1.0).rtype(), RType::Real);
190    ///     assert_eq!(r!("1").rtype(), RType::String);
191    ///     assert_eq!(r!(List::from_values(&[1, 2])).rtype(), RType::List);
192    ///     assert_eq!(parse("x + y")?.rtype(), RType::Expression);
193    ///     assert_eq!(r!(Raw::from_bytes(&[1_u8, 2, 3])).rtype(), RType::Raw);
194    /// }
195    /// ```
196    pub fn rtype(&self) -> RType {
197        match self.sexptype() {
198            NILSXP => RType::Null,
199            SYMSXP => RType::Symbol,
200            LISTSXP => RType::Pairlist,
201            CLOSXP => RType::Function,
202            ENVSXP => RType::Environment,
203            PROMSXP => RType::Promise,
204            LANGSXP => RType::Language,
205            SPECIALSXP => RType::Special,
206            BUILTINSXP => RType::Builtin,
207            CHARSXP => RType::Character,
208            LGLSXP => RType::Logical,
209            INTSXP => RType::Integer,
210            REALSXP => RType::Real,
211            CPLXSXP => RType::Complex,
212            STRSXP => RType::String,
213            DOTSXP => RType::Dot,
214            ANYSXP => RType::Any,
215            VECSXP => RType::List,
216            EXPRSXP => RType::Expression,
217            BCODESXP => RType::Bytecode,
218            EXTPTRSXP => RType::ExternalPtr,
219            WEAKREFSXP => RType::WeakRef,
220            RAWSXP => RType::Raw,
221            S4SXP => RType::S4,
222            _ => RType::Unknown,
223        }
224    }
225
226    /// Get the extended length of the object.
227    /// ```
228    /// use extendr_api::prelude::*;
229    /// test! {
230    ///
231    /// let a : Robj = r!(vec![1., 2., 3., 4.]);
232    /// assert_eq!(a.len(), 4);
233    /// }
234    /// ```
235    pub fn len(&self) -> usize {
236        unsafe { Rf_xlength(self.get()) as usize }
237    }
238
239    /// Returns `true` if the `Robj` contains no elements.
240    /// ```
241    /// use extendr_api::prelude::*;
242    /// test! {
243    ///
244    /// let a : Robj = r!(vec![0.; 0]); // length zero of numeric vector
245    /// assert_eq!(a.is_empty(), true);
246    /// }
247    /// ```
248    pub fn is_empty(&self) -> bool {
249        self.len() == 0
250    }
251
252    /// Is this object is an NA scalar?
253    /// Works for character, integer and numeric types.
254    /// ```
255    /// use extendr_api::prelude::*;
256    /// test! {
257    ///
258    /// assert_eq!(r!(NA_INTEGER).is_na(), true);
259    /// assert_eq!(r!(NA_REAL).is_na(), true);
260    /// assert_eq!(r!(NA_STRING).is_na(), true);
261    /// }
262    /// ```
263    pub fn is_na(&self) -> bool {
264        if self.len() != 1 {
265            false
266        } else {
267            unsafe {
268                let sexp = self.get();
269                match self.sexptype() {
270                    STRSXP => STRING_ELT(sexp, 0) == libR_sys::R_NaString,
271                    INTSXP => *(INTEGER(sexp)) == libR_sys::R_NaInt,
272                    LGLSXP => *(LOGICAL(sexp)) == libR_sys::R_NaInt,
273                    REALSXP => R_IsNA(*(REAL(sexp))) != 0,
274                    _ => false,
275                }
276            }
277        }
278    }
279
280    /// Get a read-only reference to the content of an integer vector.
281    /// ```
282    /// use extendr_api::prelude::*;
283    /// test! {
284    ///
285    /// let robj = r!([1, 2, 3]);
286    /// assert_eq!(robj.as_integer_slice().unwrap(), [1, 2, 3]);
287    /// }
288    /// ```
289    pub fn as_integer_slice<'a>(&self) -> Option<&'a [i32]> {
290        self.as_typed_slice()
291    }
292
293    /// Get an iterator over integer elements of this slice.
294    /// ```
295    /// use extendr_api::prelude::*;
296    /// test! {
297    ///
298    /// let robj = r!([1, 2, 3]);
299    /// let mut tot = 0;
300    /// for val in robj.as_integer_iter().unwrap() {
301    ///   tot += val;
302    /// }
303    /// assert_eq!(tot, 6);
304    /// }
305    /// ```
306    pub fn as_integer_iter(&self) -> Option<Int> {
307        self.as_integer_slice()
308            .map(|slice| Int::from_slice(self.to_owned(), slice))
309    }
310
311    /// Get a Vec<i32> copied from the object.
312    /// ```
313    /// use extendr_api::prelude::*;
314    /// test! {
315    ///
316    /// let robj = r!([1, 2, 3]);
317    /// assert_eq!(robj.as_integer_slice().unwrap(), vec![1, 2, 3]);
318    /// }
319    /// ```
320    pub fn as_integer_vector(&self) -> Option<Vec<i32>> {
321        self.as_integer_slice().map(|value| value.to_vec())
322    }
323
324    /// Get a read-only reference to the content of a logical vector
325    /// using the tri-state [Bool]. Returns None if not a logical vector.
326    /// ```
327    /// use extendr_api::prelude::*;
328    /// test! {
329    ///     let robj = r!([TRUE, FALSE, NA_LOGICAL]);
330    ///     assert_eq!(robj.as_logical_slice().unwrap(), [TRUE, FALSE, NA_LOGICAL]);
331    /// }
332    /// ```
333    pub fn as_logical_slice(&self) -> Option<&[Bool]> {
334        self.as_typed_slice()
335    }
336
337    /// Get a Vec<Bool> copied from the object
338    /// using the tri-state [Bool].
339    /// Returns None if not a logical vector.
340    /// ```
341    /// use extendr_api::prelude::*;
342    /// test! {
343    ///     let robj = r!([TRUE, FALSE, NA_LOGICAL]);
344    ///     assert_eq!(robj.as_logical_vector().unwrap(), vec![TRUE, FALSE, NA_LOGICAL]);
345    /// }
346    /// ```
347    pub fn as_logical_vector(&self) -> Option<Vec<Bool>> {
348        self.as_logical_slice().map(|value| value.to_vec())
349    }
350
351    /// Get an iterator over logical elements of this slice.
352    /// ```
353    /// use extendr_api::prelude::*;
354    /// test! {
355    ///     let robj = r!([TRUE, FALSE, NA_LOGICAL]);
356    ///     let (mut nt, mut nf, mut nna) = (0, 0, 0);
357    ///     for val in robj.as_logical_iter().unwrap() {
358    ///       match val {
359    ///         TRUE => nt += 1,
360    ///         FALSE => nf += 1,
361    ///         NA_LOGICAL => nna += 1,
362    ///         _ => ()
363    ///       }
364    ///     }
365    ///     assert_eq!((nt, nf, nna), (1, 1, 1));
366    /// }
367    /// ```
368    pub fn as_logical_iter(&self) -> Option<Logical> {
369        self.as_logical_slice()
370            .map(|slice| Logical::from_slice(self.to_owned(), slice))
371    }
372
373    /// Get a read-only reference to the content of a double vector.
374    /// Note: the slice may contain NaN or NA values.
375    /// We may introduce a "Real" type to handle this like the Bool type.
376    /// ```
377    /// use extendr_api::prelude::*;
378    /// test! {
379    ///     let robj = r!([Some(1.), None, Some(3.)]);
380    ///     let mut tot = 0.;
381    ///     for val in robj.as_real_slice().unwrap() {
382    ///       if !val.is_na() {
383    ///         tot += val;
384    ///       }
385    ///     }
386    ///     assert_eq!(tot, 4.);
387    /// }
388    /// ```
389    pub fn as_real_slice(&self) -> Option<&[f64]> {
390        self.as_typed_slice()
391    }
392
393    /// Get an iterator over real elements of this slice.
394    /// ```
395    /// use extendr_api::prelude::*;
396    /// test! {
397    ///     let robj = r!([1., 2., 3.]);
398    ///     let mut tot = 0.;
399    ///     for val in robj.as_real_iter().unwrap() {
400    ///       if !val.is_na() {
401    ///         tot += val;
402    ///       }
403    ///     }
404    ///     assert_eq!(tot, 6.);
405    /// }
406    /// ```
407    pub fn as_real_iter(&self) -> Option<Real> {
408        self.as_real_slice()
409            .map(|slice| Real::from_slice(self.to_owned(), slice))
410    }
411
412    /// Get a Vec<f64> copied from the object.
413    /// ```
414    /// use extendr_api::prelude::*;
415    /// test! {
416    ///     let robj = r!([1., 2., 3.]);
417    ///     assert_eq!(robj.as_real_vector().unwrap(), vec![1., 2., 3.]);
418    /// }
419    /// ```
420    pub fn as_real_vector(&self) -> Option<Vec<f64>> {
421        self.as_real_slice().map(|value| value.to_vec())
422    }
423
424    /// Get a read-only reference to the content of an integer or logical vector.
425    /// ```
426    /// use extendr_api::prelude::*;
427    /// test! {
428    ///     let robj = r!(Raw::from_bytes(&[1, 2, 3]));
429    ///     assert_eq!(robj.as_raw_slice().unwrap(), &[1, 2, 3]);
430    /// }
431    /// ```
432    pub fn as_raw_slice(&self) -> Option<&[u8]> {
433        self.as_typed_slice()
434    }
435
436    /// Get a read-write reference to the content of an integer or logical vector.
437    /// Note that rust slices are 0-based so `slice[1]` is the middle value.
438    /// ```
439    /// use extendr_api::prelude::*;
440    /// test! {
441    ///     let mut robj = r!([1, 2, 3]);
442    ///     let slice : & mut [i32] = robj.as_integer_slice_mut().unwrap();
443    ///     slice[1] = 100;
444    ///     assert_eq!(robj, r!([1, 100, 3]));
445    /// }
446    /// ```
447    pub fn as_integer_slice_mut(&mut self) -> Option<&mut [i32]> {
448        self.as_typed_slice_mut()
449    }
450
451    /// Get a read-write reference to the content of a double vector.
452    /// Note that rust slices are 0-based so `slice[1]` is the middle value.
453    /// ```
454    /// use extendr_api::prelude::*;
455    /// test! {
456    ///     let mut robj = r!([1.0, 2.0, 3.0]);
457    ///     let slice = robj.as_real_slice_mut().unwrap();
458    ///     slice[1] = 100.0;
459    ///     assert_eq!(robj, r!([1.0, 100.0, 3.0]));
460    /// }
461    /// ```
462    pub fn as_real_slice_mut(&mut self) -> Option<&mut [f64]> {
463        self.as_typed_slice_mut()
464    }
465
466    /// Get a read-write reference to the content of a raw vector.
467    /// ```
468    /// use extendr_api::prelude::*;
469    /// test! {
470    ///     let mut robj = r!(Raw::from_bytes(&[1, 2, 3]));
471    ///     let slice = robj.as_raw_slice_mut().unwrap();
472    ///     slice[1] = 100;
473    ///     assert_eq!(robj, r!(Raw::from_bytes(&[1, 100, 3])));
474    /// }
475    /// ```
476    pub fn as_raw_slice_mut(&mut self) -> Option<&mut [u8]> {
477        self.as_typed_slice_mut()
478    }
479
480    /// Get a vector of owned strings.
481    /// Owned strings have long lifetimes, but are much slower than references.
482    /// ```
483    /// use extendr_api::prelude::*;
484    /// test! {
485    ///    let robj1 = Robj::from("xyz");
486    ///    assert_eq!(robj1.as_string_vector(), Some(vec!["xyz".to_string()]));
487    ///    let robj2 = Robj::from(1);
488    ///    assert_eq!(robj2.as_string_vector(), None);
489    /// }
490    /// ```
491    pub fn as_string_vector(&self) -> Option<Vec<String>> {
492        self.as_str_iter()
493            .map(|iter| iter.map(str::to_string).collect())
494    }
495
496    /// Get a vector of string references.
497    /// String references (&str) are faster, but have short lifetimes.
498    /// ```
499    /// use extendr_api::prelude::*;
500    /// test! {
501    ///    let robj1 = Robj::from("xyz");
502    ///    assert_eq!(robj1.as_str_vector(), Some(vec!["xyz"]));
503    ///    let robj2 = Robj::from(1);
504    ///    assert_eq!(robj2.as_str_vector(), None);
505    /// }
506    /// ```
507    pub fn as_str_vector(&self) -> Option<Vec<&str>> {
508        self.as_str_iter().map(|iter| iter.collect())
509    }
510
511    /// Get a read-only reference to a scalar string type.
512    /// ```
513    /// use extendr_api::prelude::*;
514    /// test! {
515    ///    let robj1 = Robj::from("xyz");
516    ///    let robj2 = Robj::from(1);
517    ///    assert_eq!(robj1.as_str(), Some("xyz"));
518    ///    assert_eq!(robj2.as_str(), None);
519    /// }
520    /// ```
521    pub fn as_str<'a>(&self) -> Option<&'a str> {
522        unsafe {
523            match self.sexptype() {
524                STRSXP => {
525                    if self.len() != 1 {
526                        None
527                    } else {
528                        Some(to_str(R_CHAR(STRING_ELT(self.get(), 0)) as *const u8))
529                    }
530                }
531                // CHARSXP => Some(to_str(R_CHAR(self.get()) as *const u8)),
532                // SYMSXP => Some(to_str(R_CHAR(PRINTNAME(self.get())) as *const u8)),
533                _ => None,
534            }
535        }
536    }
537
538    /// Get a scalar integer.
539    /// ```
540    /// use extendr_api::prelude::*;
541    /// test! {
542    ///    let robj1 = Robj::from("xyz");
543    ///    let robj2 = Robj::from(1);
544    ///    let robj3 = Robj::from(NA_INTEGER);
545    ///    assert_eq!(robj1.as_integer(), None);
546    ///    assert_eq!(robj2.as_integer(), Some(1));
547    ///    assert_eq!(robj3.as_integer(), None);
548    /// }
549    /// ```
550    pub fn as_integer(&self) -> Option<i32> {
551        match self.as_integer_slice() {
552            Some(slice) if slice.len() == 1 && !slice[0].is_na() => Some(slice[0]),
553            _ => None,
554        }
555    }
556
557    /// Get a scalar real.
558    /// ```
559    /// use extendr_api::prelude::*;
560    /// test! {
561    ///    let robj1 = Robj::from(1);
562    ///    let robj2 = Robj::from(1.);
563    ///    let robj3 = Robj::from(NA_REAL);
564    ///    assert_eq!(robj1.as_real(), None);
565    ///    assert_eq!(robj2.as_real(), Some(1.));
566    ///    assert_eq!(robj3.as_real(), None);
567    /// }
568    /// ```
569    pub fn as_real(&self) -> Option<f64> {
570        match self.as_real_slice() {
571            Some(slice) if slice.len() == 1 && !slice[0].is_na() => Some(slice[0]),
572            _ => None,
573        }
574    }
575
576    /// Get a scalar rust boolean.
577    /// ```
578    /// use extendr_api::prelude::*;
579    /// test! {
580    ///    let robj1 = Robj::from(TRUE);
581    ///    let robj2 = Robj::from(1.);
582    ///    let robj3 = Robj::from(NA_LOGICAL);
583    ///    assert_eq!(robj1.as_bool(), Some(true));
584    ///    assert_eq!(robj2.as_bool(), None);
585    ///    assert_eq!(robj3.as_bool(), None);
586    /// }
587    /// ```
588    pub fn as_bool(&self) -> Option<bool> {
589        match self.as_logical_slice() {
590            Some(slice) if slice.len() == 1 && !slice[0].is_na() => Some(slice[0].into()),
591            _ => None,
592        }
593    }
594
595    /// Get a scalar boolean as a tri-boolean [Bool] value.
596    /// ```
597    /// use extendr_api::prelude::*;
598    /// test! {
599    ///    let robj1 = Robj::from(TRUE);
600    ///    let robj2 = Robj::from([TRUE, FALSE]);
601    ///    let robj3 = Robj::from(NA_LOGICAL);
602    ///    assert_eq!(robj1.as_logical(), Some(TRUE));
603    ///    assert_eq!(robj2.as_logical(), None);
604    ///    assert_eq!(robj3.as_logical(), Some(NA_LOGICAL));
605    /// }
606    /// ```
607    pub fn as_logical(&self) -> Option<Bool> {
608        match self.as_logical_slice() {
609            Some(slice) if slice.len() == 1 => Some(slice[0]),
610            _ => None,
611        }
612    }
613
614    /// Evaluate the expression in R and return an error or an R object.
615    /// ```
616    /// use extendr_api::prelude::*;
617    /// test! {
618    ///
619    ///    let add = lang!("+", 1, 2);
620    ///    assert_eq!(add.eval().unwrap(), r!(3));
621    /// }
622    /// ```
623    pub fn eval(&self) -> Result<Robj> {
624        self.eval_with_env(&global_env())
625    }
626
627    /// Evaluate the expression in R and return an error or an R object.
628    /// ```
629    /// use extendr_api::prelude::*;
630    /// test! {
631    ///
632    ///    let add = lang!("+", 1, 2);
633    ///    assert_eq!(add.eval_with_env(&global_env()).unwrap(), r!(3));
634    /// }
635    /// ```
636    pub fn eval_with_env(&self, env: &Environment) -> Result<Robj> {
637        single_threaded(|| unsafe {
638            let mut error: raw::c_int = 0;
639            let res = R_tryEval(self.get(), env.get(), &mut error as *mut raw::c_int);
640            if error != 0 {
641                Err(Error::EvalError(self.clone()))
642            } else {
643                Ok(new_owned(res))
644            }
645        })
646    }
647
648    /// Evaluate the expression and return NULL or an R object.
649    /// ```
650    /// use extendr_api::prelude::*;
651    /// test! {
652    ///    let bad = lang!("imnotavalidfunctioninR", 1, 2);
653    ///    assert_eq!(bad.eval_blind(), r!(NULL));
654    /// }
655    /// ```
656    pub fn eval_blind(&self) -> Robj {
657        let res = self.eval();
658        if let Ok(robj) = res {
659            robj
660        } else {
661            Robj::from(())
662        }
663    }
664}
665
666/// Generic access to typed slices in an Robj.
667pub trait AsTypedSlice<'a, T>
668where
669    Self: 'a,
670{
671    fn as_typed_slice(&self) -> Option<&'a [T]>
672    where
673        Self: 'a,
674    {
675        None
676    }
677
678    fn as_typed_slice_mut(&mut self) -> Option<&'a mut [T]>
679    where
680        Self: 'a,
681    {
682        None
683    }
684}
685
686macro_rules! make_typed_slice {
687    ($type: ty, $fn: tt, $($sexp: tt),* ) => {
688        impl<'a> AsTypedSlice<'a, $type> for Robj
689        where
690            Self : 'a,
691        {
692            fn as_typed_slice(&self) -> Option<&'a [$type]> {
693                match self.sexptype() {
694                    $( $sexp )|* => {
695                        unsafe {
696                            let ptr = $fn(self.get()) as *const $type;
697                            Some(std::slice::from_raw_parts(ptr, self.len()))
698                        }
699                    }
700                    _ => None
701                }
702            }
703
704            fn as_typed_slice_mut(&mut self) -> Option<&'a mut [$type]> {
705                match self.sexptype() {
706                    $( $sexp )|* => {
707                        unsafe {
708                            let ptr = $fn(self.get()) as *mut $type;
709                            Some(std::slice::from_raw_parts_mut(ptr, self.len()))
710                        }
711                    }
712                    _ => None
713                }
714            }
715        }
716    }
717}
718
719make_typed_slice!(Bool, INTEGER, LGLSXP);
720make_typed_slice!(i32, INTEGER, INTSXP);
721make_typed_slice!(f64, REAL, REALSXP);
722make_typed_slice!(u8, RAW, RAWSXP);
723
724/// These are helper functions which give access to common properties of R objects.
725#[allow(non_snake_case)]
726impl Robj {
727    /// Get a specific attribute as a borrowed robj if it exists.
728    /// ```
729    /// use extendr_api::prelude::*;
730    /// test! {
731    ///
732    ///    let mut robj = r!("hello");
733    ///    robj.set_attrib(sym!(xyz), 1);
734    ///    assert_eq!(robj.get_attrib(sym!(xyz)), Some(r!(1)));
735    /// }
736    /// ```
737    pub fn get_attrib<'a, N>(&self, name: N) -> Option<Robj>
738    where
739        Self: 'a,
740        Robj: From<N> + 'a,
741    {
742        let name = Robj::from(name);
743        if self.sexptype() == CHARSXP {
744            None
745        } else {
746            let res = unsafe { new_owned(Rf_getAttrib(self.get(), name.get())) };
747            if res.is_null() {
748                None
749            } else {
750                Some(res)
751            }
752        }
753    }
754
755    /// Set a specific attribute and return the object.
756    ///
757    /// Note that some combinations of attributes are illegal and this will
758    /// return an error.
759    /// ```
760    /// use extendr_api::prelude::*;
761    /// test! {
762    ///
763    ///    let mut robj = r!("hello").set_attrib(sym!(xyz), 1)?;
764    ///    assert_eq!(robj.get_attrib(sym!(xyz)), Some(r!(1)));
765    /// }
766    /// ```
767    pub fn set_attrib<N, V>(&self, name: N, value: V) -> Result<Robj>
768    where
769        N: Into<Robj>,
770        V: Into<Robj>,
771    {
772        let name = name.into();
773        let value = value.into();
774        unsafe {
775            single_threaded(|| {
776                catch_r_error(|| Rf_setAttrib(self.get(), name.get(), value.get()))
777                    .map(|_| self.clone())
778            })
779        }
780    }
781
782    /// Get the names attribute as a string iterator if one exists.
783    /// ```
784    /// use extendr_api::prelude::*;
785    /// test! {
786    ///    let list = list!(a = 1, b = 2, c = 3);
787    ///    let names : Vec<_> = list.names().unwrap().collect();
788    ///    assert_eq!(names, vec!["a", "b", "c"]);
789    /// }
790    /// ```
791    pub fn names(&self) -> Option<StrIter> {
792        if let Some(names) = self.get_attrib(wrapper::symbol::names_symbol()) {
793            names.as_str_iter()
794        } else {
795            None
796        }
797    }
798
799    /// Set the names attribute from a string iterator.
800    ///
801    /// Returns Error::NamesLengthMismatch if the length of the names does
802    /// not match the length of the object.
803    /// ```
804    /// use extendr_api::prelude::*;
805    /// test! {
806    ///     let mut obj = r!([1, 2, 3]).set_names(&["a", "b", "c"]).unwrap();
807    ///     assert_eq!(obj.names().unwrap().collect::<Vec<_>>(), vec!["a", "b", "c"]);
808    ///     assert_eq!(r!([1, 2, 3]).set_names(&["a", "b"]), Err(Error::NamesLengthMismatch(r!(["a", "b"]))));
809    /// }
810    /// ```
811    pub fn set_names<T>(&self, names: T) -> Result<Robj>
812    where
813        T: IntoIterator,
814        T::IntoIter: ExactSizeIterator,
815        T::Item: ToVectorValue + AsRef<str>,
816    {
817        let iter = names.into_iter();
818        let robj = iter.collect_robj();
819        if robj.len() == self.len() {
820            self.set_attrib(wrapper::symbol::names_symbol(), robj)
821        } else {
822            Err(Error::NamesLengthMismatch(robj))
823        }
824    }
825
826    /// Get the dim attribute as an integer iterator if one exists.
827    /// ```
828    /// use extendr_api::prelude::*;
829    /// test! {
830    ///
831    ///    let array = R!(array(data = c(1, 2, 3, 4), dim = c(2, 2), dimnames = list(c("x", "y"), c("a","b")))).unwrap();
832    ///    let dim : Vec<_> = array.dim().unwrap().collect();
833    ///    assert_eq!(dim, vec![2, 2]);
834    /// }
835    /// ```
836    pub fn dim(&self) -> Option<Int> {
837        if let Some(dim) = self.get_attrib(wrapper::symbol::dim_symbol()) {
838            dim.as_integer_iter()
839        } else {
840            None
841        }
842    }
843
844    /// Get the dimnames attribute as a list iterator if one exists.
845    /// ```
846    /// use extendr_api::prelude::*;
847    /// test! {
848    ///    let array = R!(array(data = c(1, 2, 3, 4), dim = c(2, 2), dimnames = list(c("x", "y"), c("a","b")))).unwrap();
849    ///    let names : Vec<_> = array.dimnames().unwrap().collect();
850    ///    assert_eq!(names, vec![r!(["x", "y"]), r!(["a", "b"])]);
851    /// }
852    /// ```
853    pub fn dimnames(&self) -> Option<ListIter> {
854        if let Some(names) = self.get_attrib(wrapper::symbol::dimnames_symbol()) {
855            names.as_list().map(|v| v.values())
856        } else {
857            None
858        }
859    }
860
861    /// Get the class attribute as a string iterator if one exists.
862    /// ```
863    /// use extendr_api::prelude::*;
864    /// test! {
865    ///    let formula = R!("y ~ A * x + b").unwrap();
866    ///    let class : Vec<_> = formula.class().unwrap().collect();
867    ///    assert_eq!(class, ["formula"]);
868    /// }
869    /// ```
870    pub fn class(&self) -> Option<StrIter> {
871        if let Some(class) = self.get_attrib(wrapper::symbol::class_symbol()) {
872            class.as_str_iter()
873        } else {
874            None
875        }
876    }
877
878    /// Set the class attribute from a string iterator, returning
879    /// a new object.
880    ///
881    /// May return an error for some class names.
882    /// ```
883    /// use extendr_api::prelude::*;
884    /// test! {
885    ///     let mut obj = r!([1, 2, 3]).set_class(&["a", "b", "c"])?;
886    ///     assert_eq!(obj.class().unwrap().collect::<Vec<_>>(), vec!["a", "b", "c"]);
887    ///     assert_eq!(obj.inherits("a"), true);
888    /// }
889    /// ```
890    pub fn set_class<T>(&self, class: T) -> Result<Robj>
891    where
892        T: IntoIterator,
893        T::IntoIter: ExactSizeIterator,
894        T::Item: ToVectorValue + AsRef<str>,
895    {
896        let iter = class.into_iter();
897        self.set_attrib(wrapper::symbol::class_symbol(), iter.collect_robj())
898    }
899
900    /// Return true if this class inherits this class.
901    /// ```
902    /// use extendr_api::prelude::*;
903    /// test! {
904    ///    let formula = R!("y ~ A * x + b").unwrap();
905    ///    assert_eq!(formula.inherits("formula"), true);
906    /// }
907    /// ```
908    pub fn inherits(&self, classname: &str) -> bool {
909        if let Some(mut iter) = self.class() {
910            iter.any(|n| n == classname)
911        } else {
912            false
913        }
914    }
915
916    /// Get the levels attribute as a string iterator if one exists.
917    /// ```
918    /// use extendr_api::prelude::*;
919    /// test! {
920    ///    let factor = factor!(vec!["abcd", "def", "fg", "fg"]);
921    ///    let levels : Vec<_> = factor.levels().unwrap().collect();
922    ///    assert_eq!(levels, vec!["abcd", "def", "fg"]);
923    /// }
924    /// ```
925    pub fn levels(&self) -> Option<StrIter> {
926        if let Some(levels) = self.get_attrib(wrapper::symbol::levels_symbol()) {
927            levels.as_str_iter()
928        } else {
929            None
930        }
931    }
932}
933
934#[doc(hidden)]
935pub unsafe fn new_owned(sexp: SEXP) -> Robj {
936    single_threaded(|| ownership::protect(sexp));
937    Robj::Owned(sexp)
938}
939
940#[doc(hidden)]
941pub unsafe fn new_sys(sexp: SEXP) -> Robj {
942    Robj::Sys(sexp)
943}
944
945/// Compare equality with integer slices.
946impl<'a> PartialEq<[i32]> for Robj {
947    fn eq(&self, rhs: &[i32]) -> bool {
948        self.as_integer_slice() == Some(rhs)
949    }
950}
951
952/// Compare equality with slices of double.
953impl<'a> PartialEq<[f64]> for Robj {
954    fn eq(&self, rhs: &[f64]) -> bool {
955        self.as_real_slice() == Some(rhs)
956    }
957}
958
959/// Compare equality with strings.
960impl PartialEq<str> for Robj {
961    fn eq(&self, rhs: &str) -> bool {
962        self.as_str() == Some(rhs)
963    }
964}
965
966/// Compare equality with two Robjs.
967impl PartialEq<Robj> for Robj {
968    fn eq(&self, rhs: &Robj) -> bool {
969        unsafe {
970            if self.get() == rhs.get() {
971                return true;
972            }
973
974            // see https://github.com/hadley/r-internals/blob/master/misc.md
975            R_compute_identical(self.get(), rhs.get(), 16) != 0
976        }
977    }
978}
979
980/// Implement {:?} formatting.
981impl std::fmt::Debug for Robj {
982    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
983        match self.sexptype() {
984            NILSXP => write!(f, "r!(NULL)"),
985            SYMSXP => {
986                if self.is_missing_arg() {
987                    write!(f, "missing_arg()")
988                } else if self.is_unbound_value() {
989                    write!(f, "unbound_value()")
990                } else {
991                    write!(f, "sym!({})", self.as_symbol().unwrap().as_str())
992                }
993            }
994            LISTSXP => {
995                let pairlist = self.as_pairlist().unwrap().iter();
996                write!(f, "r!({:?})", pairlist)
997            }
998            CLOSXP => {
999                let func = self.as_function().unwrap();
1000                let formals = func.formals();
1001                let body = func.body();
1002                let environment = func.environment();
1003                write!(
1004                    f,
1005                    "r!(Function::from_parts({:?}, {:?}, {:?}))",
1006                    formals, body, environment
1007                )
1008            }
1009            ENVSXP => unsafe {
1010                let sexp = self.get();
1011                if sexp == R_GlobalEnv {
1012                    write!(f, "global_env()")
1013                } else if sexp == R_BaseEnv {
1014                    write!(f, "base_env()")
1015                } else if sexp == R_EmptyEnv {
1016                    write!(f, "empty_env()")
1017                } else {
1018                    write!(f, "r!(Environment::from_pairs(...))")
1019                }
1020            },
1021            PROMSXP => {
1022                let p = self.as_promise().unwrap();
1023                write!(
1024                    f,
1025                    "r!(Promise::from_parts({:?}, {:?}))",
1026                    p.code(),
1027                    p.environment()
1028                )
1029            }
1030            LANGSXP => write!(
1031                f,
1032                "r!(Language::from_values({:?}))",
1033                self.as_language().unwrap().values().collect::<Vec<_>>()
1034            ),
1035            SPECIALSXP => write!(f, "r!(Special())"),
1036            BUILTINSXP => write!(f, "r!(Builtin())"),
1037            CHARSXP => {
1038                let c = Character::try_from(self.clone()).unwrap();
1039                write!(f, "r!(Character::from_string({:?}))", c.as_str())
1040            }
1041            LGLSXP => {
1042                let slice = self.as_logical_slice().unwrap();
1043                if slice.len() == 1 {
1044                    write!(f, "r!({:?})", slice[0])
1045                } else {
1046                    write!(f, "r!({:?})", slice)
1047                }
1048            }
1049            INTSXP => {
1050                let slice = self.as_integer_slice().unwrap();
1051                if slice.len() == 1 {
1052                    write!(f, "r!({:?})", slice[0])
1053                } else {
1054                    write!(f, "r!({:?})", self.as_integer_slice().unwrap())
1055                }
1056            }
1057            REALSXP => {
1058                let slice = self.as_real_slice().unwrap();
1059                if slice.len() == 1 {
1060                    write!(f, "r!({:?})", slice[0])
1061                } else {
1062                    write!(f, "r!({:?})", slice)
1063                }
1064            }
1065            VECSXP => {
1066                let list = self.as_list().unwrap();
1067                if self.names().is_some() {
1068                    write!(f, "r!(List::from_pairs({:?}))", list.iter())
1069                } else {
1070                    write!(f, "r!(List::from_values({:?}))", list.values())
1071                }
1072            }
1073            EXPRSXP => write!(
1074                f,
1075                "r!(Expression::from_values({:?}))",
1076                self.as_expression().unwrap().values()
1077            ),
1078            WEAKREFSXP => write!(f, "r!(Weakref())"),
1079            // CPLXSXP => false,
1080            STRSXP => {
1081                write!(f, "r!([")?;
1082                let mut sep = "";
1083                for s in self.as_str_iter().unwrap() {
1084                    // if s.is_na() {
1085                    //     write!(f, "{}na_str()", sep)?;
1086                    // } else {
1087                    write!(f, "{}{:?}", sep, s)?;
1088                    // }
1089                    sep = ", ";
1090                }
1091                write!(f, "])")
1092            }
1093            DOTSXP => write!(f, "r!(Dot())"),
1094            ANYSXP => write!(f, "r!(Any())"),
1095            BCODESXP => write!(f, "r!(Bcode())"),
1096            EXTPTRSXP => write!(f, "r!(Extptr())"),
1097            RAWSXP => {
1098                write!(
1099                    f,
1100                    "r!(Raw::from_bytes({:?}))",
1101                    self.as_raw().unwrap().as_slice()
1102                )
1103            }
1104            S4SXP => write!(f, "r!(S4())"),
1105            NEWSXP => write!(f, "r!(New())"),
1106            FREESXP => write!(f, "r!(Free())"),
1107            _ => write!(f, "??"),
1108        }?;
1109        if let Some(c) = self.class() {
1110            write!(f, ".set_class({:?}", c)?;
1111        }
1112        Ok(())
1113    }
1114}
1115
1116// Internal utf8 to str conversion.
1117// Lets not worry about non-ascii/unicode strings for now (or ever).
1118pub(crate) unsafe fn to_str<'a>(ptr: *const u8) -> &'a str {
1119    let mut len = 0;
1120    loop {
1121        if *ptr.offset(len) == 0 {
1122            break;
1123        }
1124        len += 1;
1125    }
1126    let slice = std::slice::from_raw_parts(ptr, len as usize);
1127    std::str::from_utf8_unchecked(slice)
1128}
1129
1130/// Release any owned objects.
1131impl Drop for Robj {
1132    fn drop(&mut self) {
1133        unsafe {
1134            match self {
1135                Robj::Owned(sexp) => ownership::unprotect(*sexp),
1136                Robj::Sys(_) => (),
1137            }
1138        }
1139    }
1140}