extendr_api/wrapper/
macros.rs
1macro_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 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 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 fn from_iter<T: IntoIterator<Item = $scalar_type>>(iter: T) -> Self {
138 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 fn from_iter<T: IntoIterator<Item = $collect_from_type>>(iter: T) -> Self {
167 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 fn from_iter<T: IntoIterator<Item = &'a $collect_from_type>>(iter: T) -> Self {
186 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;