miniextendr_api/from_r/
na_vectors.rs1use crate::coerce::TryCoerce;
27use crate::from_r::{
28 SexpError, SexpNaError, SexpTypeError, TryFromSexp, charsxp_to_str, coerce_value,
29 from_numeric_vec_with, is_na_real, map_strsxp_with, r_slice,
30};
31use crate::{RLogical, Rboolean, SEXP, SEXPTYPE, SexpExt};
32
33macro_rules! impl_vec_option_try_from_sexp {
35 ($t:ty, $sexptype:ident, $dataptr:ident, $is_na:expr) => {
36 impl TryFromSexp for Vec<Option<$t>> {
37 type Error = SexpError;
38
39 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
40 let actual = sexp.type_of();
41 if actual != SEXPTYPE::$sexptype {
42 return Err(SexpTypeError {
43 expected: SEXPTYPE::$sexptype,
44 actual,
45 }
46 .into());
47 }
48
49 let len = sexp.len();
50 let ptr = unsafe { crate::sys::$dataptr(sexp) };
51 let slice = unsafe { r_slice(ptr, len) };
52
53 Ok(slice
54 .iter()
55 .map(|&v| if $is_na(v) { None } else { Some(v) })
56 .collect())
57 }
58 }
59 };
60}
61
62impl_vec_option_try_from_sexp!(f64, REALSXP, REAL, is_na_real);
63impl_vec_option_try_from_sexp!(i32, INTSXP, INTEGER, |v: i32| v == i32::MIN);
64
65impl TryFromSexp for Vec<Option<bool>> {
67 type Error = SexpError;
68
69 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
70 let actual = sexp.type_of();
71 if actual != SEXPTYPE::LGLSXP {
72 return Err(SexpTypeError {
73 expected: SEXPTYPE::LGLSXP,
74 actual,
75 }
76 .into());
77 }
78
79 let slice: &[RLogical] = unsafe { sexp.as_slice() };
80
81 Ok(slice.iter().map(|v| v.to_option_bool()).collect())
82 }
83
84 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
85 let actual = sexp.type_of();
86 if actual != SEXPTYPE::LGLSXP {
87 return Err(SexpTypeError {
88 expected: SEXPTYPE::LGLSXP,
89 actual,
90 }
91 .into());
92 }
93
94 let slice: &[RLogical] = unsafe { sexp.as_slice_unchecked() };
95
96 Ok(slice.iter().map(|v| v.to_option_bool()).collect())
97 }
98}
99
100impl TryFromSexp for Vec<Rboolean> {
102 type Error = SexpError;
103
104 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
105 let actual = sexp.type_of();
106 if actual != SEXPTYPE::LGLSXP {
107 return Err(SexpTypeError {
108 expected: SEXPTYPE::LGLSXP,
109 actual,
110 }
111 .into());
112 }
113
114 let slice: &[RLogical] = unsafe { sexp.as_slice() };
115
116 slice
117 .iter()
118 .map(|v| match v.to_option_bool() {
119 Some(false) => Ok(Rboolean::FALSE),
120 Some(true) => Ok(Rboolean::TRUE),
121 None => Err(SexpNaError {
122 sexp_type: SEXPTYPE::LGLSXP,
123 }
124 .into()),
125 })
126 .collect()
127 }
128}
129
130impl TryFromSexp for Vec<Option<Rboolean>> {
132 type Error = SexpError;
133
134 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
135 let actual = sexp.type_of();
136 if actual != SEXPTYPE::LGLSXP {
137 return Err(SexpTypeError {
138 expected: SEXPTYPE::LGLSXP,
139 actual,
140 }
141 .into());
142 }
143
144 let slice: &[RLogical] = unsafe { sexp.as_slice() };
145
146 Ok(slice
147 .iter()
148 .map(|v| match v.to_option_bool() {
149 Some(false) => Some(Rboolean::FALSE),
150 Some(true) => Some(Rboolean::TRUE),
151 None => None,
152 })
153 .collect())
154 }
155}
156
157impl TryFromSexp for Vec<crate::altrep_data::Logical> {
163 type Error = SexpError;
164
165 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
166 let actual = sexp.type_of();
167 if actual != SEXPTYPE::LGLSXP {
168 return Err(SexpTypeError {
169 expected: SEXPTYPE::LGLSXP,
170 actual,
171 }
172 .into());
173 }
174
175 let slice: &[RLogical] = unsafe { sexp.as_slice() };
176
177 Ok(slice
178 .iter()
179 .map(|&v| crate::altrep_data::Logical::from(v))
180 .collect())
181 }
182}
183
184impl TryFromSexp for Vec<Option<RLogical>> {
186 type Error = SexpError;
187
188 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
189 let actual = sexp.type_of();
190 if actual != SEXPTYPE::LGLSXP {
191 return Err(SexpTypeError {
192 expected: SEXPTYPE::LGLSXP,
193 actual,
194 }
195 .into());
196 }
197
198 let slice: &[RLogical] = unsafe { sexp.as_slice() };
199
200 Ok(slice
201 .iter()
202 .map(|v| if v.is_na() { None } else { Some(*v) })
203 .collect())
204 }
205}
206
207impl TryFromSexp for Vec<Option<String>> {
211 type Error = SexpError;
212
213 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
214 map_strsxp_with(sexp, |charsxp, _i| {
215 if charsxp == SEXP::na_string() {
216 Ok(None)
217 } else {
218 Ok(Some(unsafe { charsxp_to_str(charsxp) }.to_owned()))
219 }
220 })
221 }
222}
223
224impl TryFromSexp for Vec<Option<u8>> {
226 type Error = SexpError;
227
228 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
229 let actual = sexp.type_of();
230 if actual != SEXPTYPE::RAWSXP {
231 return Err(SexpTypeError {
232 expected: SEXPTYPE::RAWSXP,
233 actual,
234 }
235 .into());
236 }
237
238 let slice: &[u8] = unsafe { sexp.as_slice() };
239
240 Ok(slice.iter().map(|&v| Some(v)).collect())
241 }
242}
243
244#[inline]
245fn try_from_sexp_numeric_option_vec<T>(sexp: SEXP) -> Result<Vec<Option<T>>, SexpError>
246where
247 i32: TryCoerce<T>,
248 f64: TryCoerce<T>,
249 u8: TryCoerce<T>,
250 <i32 as TryCoerce<T>>::Error: std::fmt::Debug,
251 <f64 as TryCoerce<T>>::Error: std::fmt::Debug,
252 <u8 as TryCoerce<T>>::Error: std::fmt::Debug,
253{
254 from_numeric_vec_with(
255 sexp,
256 |v: i32| {
257 if v == crate::altrep_traits::NA_INTEGER {
258 Ok(None)
259 } else {
260 coerce_value(v).map(Some)
261 }
262 },
263 |v: f64| {
264 if is_na_real(v) {
265 Ok(None)
266 } else {
267 coerce_value(v).map(Some)
268 }
269 },
270 |v: u8| coerce_value(v).map(Some),
272 |v: RLogical| {
273 if v.is_na() {
274 Ok(None)
275 } else {
276 coerce_value(v.to_i32()).map(Some)
277 }
278 },
279 )
280}
281
282macro_rules! impl_vec_option_try_from_sexp_numeric {
283 ($t:ty) => {
284 impl TryFromSexp for Vec<Option<$t>> {
285 type Error = SexpError;
286
287 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
288 try_from_sexp_numeric_option_vec(sexp)
289 }
290
291 unsafe fn try_from_sexp_unchecked(sexp: SEXP) -> Result<Self, Self::Error> {
292 try_from_sexp_numeric_option_vec(sexp)
293 }
294 }
295 };
296}
297
298impl_vec_option_try_from_sexp_numeric!(i8);
299impl_vec_option_try_from_sexp_numeric!(i16);
300impl_vec_option_try_from_sexp_numeric!(u16);
301impl_vec_option_try_from_sexp_numeric!(u32);
302impl_vec_option_try_from_sexp_numeric!(i64);
303impl_vec_option_try_from_sexp_numeric!(u64);
304impl_vec_option_try_from_sexp_numeric!(isize);
305impl_vec_option_try_from_sexp_numeric!(usize);
306impl_vec_option_try_from_sexp_numeric!(f32);
307