Skip to main content

extendr_api/wrapper/
macros.rs

1/// Generates `impl` block and required traits for a vector type.
2macro_rules! gen_vector_wrapper_impl {
3    (
4        vector_type: $type : ident,
5        scalar_type: $scalar_type : ty,
6        primitive_type: $primitive_type : ty,
7        r_prefix: $r_prefix : ident,
8        SEXP: $sexp : ident,
9        doc_name: $doc_name : ident,
10        altrep_constructor: $altrep_constructor : ident,
11    ) => {
12
13        impl Attributes for $type {}
14
15        impl Default for $type {
16            fn default() -> Self {
17                $type::new(0)
18            }
19        }
20
21        impl From<Option<$type>> for Robj {
22            fn from(value: Option<$type>) -> Self {
23                match value {
24                    None => nil_value(),
25                    Some(value) => value.into(),
26                }
27            }
28        }
29
30        impl $type {
31            paste::paste!{
32                #[doc = "Create a new vector of " $type:lower "."]
33                #[doc = "```"]
34                #[doc = "use extendr_api::prelude::*;"]
35                #[doc = "test! {"]
36                #[doc = "   let vec = " $type "::new(10);"]
37                #[doc = "   assert_eq!(vec.is_" $r_prefix:lower "(), true);"]
38                #[doc = "   assert_eq!(vec.len(), 10);"]
39                #[doc = "}"]
40                #[doc = "```"]
41                /// Constructs an empty vector of size `len` with default values
42                pub fn new(len: usize) -> $type {
43                    // TODO: Check if impacts performance.
44                    let iter = (0..len).map(|_| <$primitive_type>::default());
45                    <$type>::from_values(iter)
46                }
47
48                /// Constructs a new vector of size `len` with `NA` values
49                pub fn new_with_na(len: usize) -> $type {
50                    let iter = (0..len).map(|_| <$primitive_type>::na());
51                    <$type>::from_values(iter)
52                }
53            }
54            paste::paste!{
55                #[doc = "Wrapper for creating non-ALTREP " $doc_name " (" $sexp ") vectors from iterators."]
56                #[doc = "The iterator must be exact."]
57                #[doc = "If you want a more generalised constructor, use `iter.collect::<" $type ">()`."]
58                pub fn from_values<V>(values: V) -> Self
59                where
60                    V: IntoIterator,
61                    V::IntoIter: ExactSizeIterator,
62                    V::Item: Into<$scalar_type>,
63                {
64                    single_threaded(|| {
65                        let values: V::IntoIter = values.into_iter();
66
67                        let mut robj = Robj::alloc_vector($sexp, values.len());
68                        let dest: &mut [$scalar_type] = robj.as_typed_slice_mut().unwrap();
69
70                        for (d, v) in dest.iter_mut().zip(values) {
71                            *d = v.into();
72                        }
73                        Self { robj }
74                    })
75                }
76            }
77
78            paste::paste!{
79                #[doc = "Wrapper for creating ALTREP " $doc_name " (" $sexp ") vectors from iterators."]
80                #[doc = "The iterator must be exact, cloneable and implement Debug."]
81                #[doc = "If you want a more generalised constructor, use `iter.collect::<" $type ">()`."]
82                pub fn from_values_altrep<V>(values: V) -> Self
83                where
84                    V: IntoIterator,
85                    V::IntoIter: ExactSizeIterator + std::fmt::Debug + Clone + 'static + std::any::Any,
86                    V::Item: Into<$scalar_type>,
87                {
88                    single_threaded(|| {
89                        let values: V::IntoIter = values.into_iter();
90
91                        let robj =
92                                  Altrep::$altrep_constructor(values)
93                                .try_into()
94                                .unwrap();
95                        Self { robj }
96                    })
97                }
98            }
99
100            paste::paste! {
101                #[doc = "Get a single element from the vector."]
102                #[doc = "Note that this is very inefficient in a tight loop."]
103                #[doc = "```"]
104                #[doc = "use extendr_api::prelude::*;"]
105                #[doc = "test! {"]
106                #[doc = "   let vec = " $type "::new(10);"]
107                #[doc = "   assert_eq!(vec.elt(0), <"$scalar_type ">::default());"]
108                #[doc = "   assert_eq!(vec.elt(9), <"$scalar_type ">::default());"]
109                #[doc = "   assert!(vec.elt(10).is_na());"]
110                #[doc = "}"]
111                #[doc = "```"]
112                pub fn elt(&self, index: usize) -> $scalar_type {
113                    use extendr_ffi::{R_xlen_t};
114                    // Defensive check for oob
115                    // This check will not be needed in later releases of R
116                    if(index >= self.len()) {
117                        <$scalar_type>::na()
118                    } else {
119                        unsafe { extendr_ffi::[<$r_prefix _ELT>](self.get(), index as R_xlen_t).into() }
120                    }
121                }
122            }
123
124            paste::paste!{
125                #[doc = "Return an iterator for a " $doc_name " object."]
126                #[doc = "Forces ALTREP objects to manifest."]
127                pub fn iter(&self) -> impl Iterator<Item = $scalar_type> {
128                    self.as_robj().as_typed_slice().unwrap().iter().cloned()
129                }
130            }
131
132            paste::paste!{
133                #[doc = "Return a writable iterator for a " $doc_name " object."]
134                #[doc = "Forces ALTREP objects to manifest."]
135                pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut $scalar_type> {
136                    self.as_robj_mut().as_typed_slice_mut().unwrap().iter_mut()
137                }
138            }
139        }
140
141        impl FromIterator<$scalar_type> for $type {
142            /// A more generalised iterator collector for small vectors.
143            /// Generates a non-ALTREP vector.
144            fn from_iter<T: IntoIterator<Item = $scalar_type>>(iter: T) -> Self {
145                // Collect into a vector first.
146                // TODO: specialise for ExactSizeIterator.
147                let values: Vec<$scalar_type> = iter.into_iter().collect();
148
149                let mut robj = Robj::alloc_vector($sexp, values.len());
150                let dest: &mut [$scalar_type] = robj.as_typed_slice_mut().unwrap();
151
152                for (d, v) in dest.iter_mut().zip(values) {
153                    *d = v;
154                }
155
156                $type { robj }
157            }
158        }
159    }
160}
161
162macro_rules! gen_from_iterator_impl {
163    (
164        vector_type: $type : ident,
165        collect_from_type: $collect_from_type : ty,
166        underlying_type: $underlying_type : ty,
167        SEXP: $sexp : ident,
168        assignment: $assignment : expr
169    ) => {
170        impl FromIterator<$collect_from_type> for $type {
171            /// A more generalised iterator collector for small vectors.
172            /// Generates a non-ALTREP vector.
173            fn from_iter<T: IntoIterator<Item = $collect_from_type>>(iter: T) -> Self {
174                // Collect into a vector first.
175                // TODO: specialise for ExactSizeIterator.
176                let values: Vec<$collect_from_type> = iter.into_iter().collect();
177
178                let mut robj = Robj::alloc_vector($sexp, values.len());
179                let dest: &mut [$underlying_type] = robj.as_typed_slice_mut().unwrap();
180
181                for (d, v) in dest.iter_mut().zip(values) {
182                    $assignment(d, v)
183                }
184
185                $type { robj }
186            }
187        }
188
189        impl<'a> FromIterator<&'a $collect_from_type> for $type {
190            /// A more generalised iterator collector for small vectors.
191            /// Generates a non-ALTREP vector.
192            fn from_iter<T: IntoIterator<Item = &'a $collect_from_type>>(iter: T) -> Self {
193                // Collect into a vector first.
194                // TODO: specialise for ExactSizeIterator.
195                let values: Vec<&'a $collect_from_type> = iter.into_iter().collect();
196
197                let mut robj = Robj::alloc_vector($sexp, values.len());
198                let dest: &mut [$underlying_type] = robj.as_typed_slice_mut().unwrap();
199
200                for (d, v) in dest.iter_mut().zip(values) {
201                    $assignment(d, *v)
202                }
203
204                $type { robj }
205            }
206        }
207    };
208}
209
210pub(in crate::wrapper) use gen_from_iterator_impl;
211pub(in crate::wrapper) use gen_vector_wrapper_impl;