extendr_api/wrapper/
integers.rs

1use super::scalar::{Rint, Scalar};
2use super::*;
3use extendr_ffi::{
4    dataptr, R_xlen_t, INTEGER_GET_REGION, INTEGER_IS_SORTED, INTEGER_NO_NA, SET_INTEGER_ELT,
5};
6use std::iter::FromIterator;
7
8/// An obscure `NA`-aware wrapper for R's integer vectors.
9/// Can be used to iterate over vectors obtained from R
10/// or to create new vectors that can be returned back to R.
11/// ```
12/// use extendr_api::prelude::*;
13/// test! {
14///     let mut vec = (0..5).collect::<Integers>();
15///     vec.iter_mut().for_each(|v| *v = *v + 10);
16///     assert_eq!(vec.elt(0), 10);
17///     let sum = vec.iter().sum::<Rint>();
18///     assert_eq!(sum, 60);
19/// }
20/// ```
21#[derive(PartialEq, Clone)]
22pub struct Integers {
23    pub(crate) robj: Robj,
24}
25
26use extendr_ffi::SEXPTYPE::INTSXP;
27macros::gen_vector_wrapper_impl!(
28    vector_type: Integers, // Implements for
29    scalar_type: Rint,     // Element type
30    primitive_type: i32,   // Raw element type
31    r_prefix: INTEGER,     // `R` functions prefix
32    SEXP: INTSXP,          // `SEXP`
33    doc_name: integer,     // Singular type name used in docs
34    altrep_constructor: make_altinteger_from_iterator,
35);
36
37macros::gen_from_iterator_impl!(
38    vector_type: Integers,
39    collect_from_type: i32,
40    underlying_type: i32,
41    SEXP: INTSXP,
42    assignment: |dest: &mut i32, val: i32| *dest = val
43);
44
45impl Integers {
46    /// Get a region of elements from the vector.
47    pub fn get_region(&self, index: usize, dest: &mut [Rint]) -> usize {
48        unsafe {
49            let ptr: *mut i32 = dest.as_mut_ptr() as *mut i32;
50            INTEGER_GET_REGION(self.get(), index as R_xlen_t, dest.len() as R_xlen_t, ptr) as usize
51        }
52    }
53
54    /// Return `TRUE` if the vector is sorted, `FALSE` if not, or `NA_BOOL` if unknown.
55    pub fn is_sorted(&self) -> Rbool {
56        unsafe { INTEGER_IS_SORTED(self.get()).into() }
57    }
58
59    /// Return `TRUE` if the vector has no `NA`s, `FALSE` if any, or `NA_BOOL` if unknown.
60    pub fn no_na(&self) -> Rbool {
61        unsafe { INTEGER_NO_NA(self.get()).into() }
62    }
63}
64
65// TODO: this should be a trait.
66impl Integers {
67    pub fn set_elt(&mut self, index: usize, val: Rint) {
68        single_threaded(|| unsafe {
69            SET_INTEGER_ELT(self.get(), index as R_xlen_t, val.inner());
70        })
71    }
72}
73
74impl Deref for Integers {
75    type Target = [Rint];
76
77    /// Treat Integers as if it is a slice, like `Vec<Rint>`
78    fn deref(&self) -> &Self::Target {
79        unsafe {
80            let ptr = dataptr(self.get()) as *const Rint;
81            std::slice::from_raw_parts(ptr, self.len())
82        }
83    }
84}
85
86impl DerefMut for Integers {
87    /// Treat Integers as if it is a mutable slice, like `Vec<Rint>`
88    fn deref_mut(&mut self) -> &mut Self::Target {
89        unsafe {
90            let ptr = dataptr(self.get_mut()) as *mut Rint;
91            std::slice::from_raw_parts_mut(ptr, self.len())
92        }
93    }
94}
95
96impl std::fmt::Debug for Integers {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        if self.len() == 1 {
99            write!(f, "{:?}", self.elt(0))
100        } else {
101            f.debug_list().entries(self.iter()).finish()
102        }
103    }
104}
105
106impl TryFrom<Vec<i32>> for Integers {
107    type Error = Error;
108
109    fn try_from(value: Vec<i32>) -> std::result::Result<Self, Self::Error> {
110        Ok(Self { robj: value.into() })
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use crate as extendr_api;
117    use crate::prelude::*;
118
119    #[test]
120    fn from_iterator() {
121        test! {
122            let vec : Integers = (0..3).collect();
123            assert_eq!(vec, Integers::from_values([0, 1, 2]));
124        }
125    }
126
127    #[test]
128    fn iter_mut() {
129        test! {
130            let mut vec = Integers::from_values(0..3);
131            vec.iter_mut().for_each(|v| *v += 1);
132            assert_eq!(vec, Integers::from_values(1..4));
133        }
134    }
135
136    #[test]
137    fn iter() {
138        test! {
139            let vec = Integers::from_values(0..3);
140            assert_eq!(vec.iter().sum::<Rint>(), 3);
141        }
142    }
143
144    #[test]
145    fn from_values_short() {
146        test! {
147            // Short (<64k) vectors are allocated.
148            let vec = Integers::from_values((0..3).map(|i| 2-i));
149            assert_eq!(vec.is_altrep(), false);
150            assert_eq!(r!(vec.clone()), r!([2, 1, 0]));
151            assert_eq!(vec.elt(1), 1);
152            let mut dest = [0.into(); 2];
153            vec.get_region(1, &mut dest);
154            assert_eq!(dest, [1, 0]);
155        }
156    }
157
158    #[test]
159    fn from_values_altrep() {
160        test! {
161            let vec = Integers::from_values_altrep(0..1000000000);
162            assert_eq!(vec.is_altrep(), true);
163            assert_eq!(vec.elt(12345678), 12345678);
164            let mut dest = [0.into(); 2];
165            vec.get_region(12345678, &mut dest);
166            assert_eq!(dest, [12345678, 12345679]);
167        }
168    }
169
170    #[test]
171    fn new() {
172        test! {
173            let vec = Integers::new(10);
174            assert_eq!(vec.is_integer(), true);
175            assert_eq!(vec.len(), 10);
176        }
177    }
178
179    #[test]
180    fn test_vec_i32_integers_conversion() {
181        test! {
182            let int_vec = vec![3,4,0,-2];
183            let int_vec_robj: Robj = int_vec.clone().try_into().unwrap();
184            // unsafe { extendr_ffi::Rf_PrintValue(rint_vec_robj.get())}
185            assert_eq!(int_vec_robj.as_integer_slice().unwrap(), &int_vec);
186        }
187    }
188}