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