miniextendr_api/altrep_impl/
arrays.rs1macro_rules! impl_altrep_array_numeric {
19 (
20 elem = $elem:ty,
21 data_trait = $data_trait:path,
22 alt_trait = $alt_trait:path,
23 rbase = $rbase:expr,
24 make_class_fn = $make_class_fn:path,
25 install_family_fn = $install_family_fn:ident
26 $(, extra { $($extra:tt)* } )?
27 $(,)?
28 ) => {
29 impl<const N: usize> crate::altrep_traits::Altrep for [$elem; N] {
30 fn length(x: crate::SEXP) -> crate::R_xlen_t {
31 let data = unsafe {
32 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
33 };
34 crate::altrep_data::AltrepLen::len(data) as crate::R_xlen_t
35 }
36 }
37
38 impl<const N: usize> crate::altrep_traits::AltVec for [$elem; N] {
39 const HAS_DATAPTR: bool = true;
40
41 fn dataptr(x: crate::SEXP, _writable: bool) -> *mut core::ffi::c_void {
42 let data = unsafe {
43 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
44 };
45 data.as_mut_ptr().cast::<core::ffi::c_void>()
46 }
47 }
48
49 impl<const N: usize> $alt_trait for [$elem; N] {
50 const HAS_ELT: bool = true;
51
52 fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> $elem {
53 let data = unsafe {
54 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
55 };
56 <[$elem; N] as $data_trait>::elt(data, i.max(0) as usize)
57 }
58
59 const HAS_GET_REGION: bool = true;
60
61 fn get_region(
62 x: crate::SEXP,
63 start: crate::R_xlen_t,
64 len: crate::R_xlen_t,
65 buf: &mut [$elem],
66 ) -> crate::R_xlen_t {
67 if start < 0 || len <= 0 {
68 return 0;
69 }
70 let data = unsafe {
71 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
72 };
73 <[$elem; N] as $data_trait>::get_region(data, start as usize, len as usize, buf)
74 as crate::R_xlen_t
75 }
76
77 $($($extra)*)?
78 }
79
80 impl<const N: usize> crate::altrep_data::InferBase for [$elem; N] {
81 const BASE: crate::altrep::RBase = $rbase;
82
83 unsafe fn make_class(
84 class_name: *const i8,
85 pkg_name: *const i8,
86 ) -> crate::sys::altrep::R_altrep_class_t {
87 let cls = unsafe { $make_class_fn(class_name, pkg_name, crate::altrep_dll_info()) };
88 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
89 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
90 }
91
92 unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
93 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
94 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
95 unsafe { crate::altrep_bridge::$install_family_fn::<Self>(cls) };
96 }
97 }
98 };
99}
100
101macro_rules! altrep_array_no_na {
103 ($elem:ty, $data_trait:path) => {
104 const HAS_NO_NA: bool = true;
105
106 fn no_na(x: crate::SEXP) -> i32 {
107 let data =
108 unsafe { <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
109 <[$elem; N] as $data_trait>::no_na(data)
110 .map(i32::from)
111 .unwrap_or(0)
112 }
113 };
114}
115
116impl_altrep_array_numeric!(
117 elem = i32,
118 data_trait = crate::altrep_data::AltIntegerData,
119 alt_trait = crate::altrep_traits::AltInteger,
120 rbase = crate::altrep::RBase::Int,
121 make_class_fn = crate::sys::altrep::R_make_altinteger_class,
122 install_family_fn = install_int,
123 extra { altrep_array_no_na!(i32, crate::altrep_data::AltIntegerData); },
124);
125impl_altrep_array_numeric!(
126 elem = f64,
127 data_trait = crate::altrep_data::AltRealData,
128 alt_trait = crate::altrep_traits::AltReal,
129 rbase = crate::altrep::RBase::Real,
130 make_class_fn = crate::sys::altrep::R_make_altreal_class,
131 install_family_fn = install_real,
132 extra { altrep_array_no_na!(f64, crate::altrep_data::AltRealData); },
133);
134impl_altrep_array_numeric!(
135 elem = u8,
136 data_trait = crate::altrep_data::AltRawData,
137 alt_trait = crate::altrep_traits::AltRaw,
138 rbase = crate::altrep::RBase::Raw,
139 make_class_fn = crate::sys::altrep::R_make_altraw_class,
140 install_family_fn = install_raw,
141);
142impl_altrep_array_numeric!(
143 elem = crate::Rcomplex,
144 data_trait = crate::altrep_data::AltComplexData,
145 alt_trait = crate::altrep_traits::AltComplex,
146 rbase = crate::altrep::RBase::Complex,
147 make_class_fn = crate::sys::altrep::R_make_altcomplex_class,
148 install_family_fn = install_cplx,
149);
150
151impl<const N: usize> crate::altrep_traits::Altrep for [bool; N] {
153 fn length(x: crate::SEXP) -> crate::R_xlen_t {
154 let data =
155 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
156 crate::altrep_data::AltrepLen::len(data) as crate::R_xlen_t
157 }
158}
159
160impl<const N: usize> crate::altrep_traits::AltVec for [bool; N] {}
161
162impl<const N: usize> crate::altrep_traits::AltLogical for [bool; N] {
163 const HAS_ELT: bool = true;
164
165 fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> i32 {
166 let data =
167 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
168 <[bool; N] as crate::altrep_data::AltLogicalData>::elt(data, i.max(0) as usize).to_r_int()
169 }
170
171 const HAS_NO_NA: bool = true;
172
173 fn no_na(x: crate::SEXP) -> i32 {
174 let data =
175 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
176 <[bool; N] as crate::altrep_data::AltLogicalData>::no_na(data)
177 .map(i32::from)
178 .unwrap_or(0)
179 }
180}
181
182impl<const N: usize> crate::altrep_data::InferBase for [bool; N] {
183 const BASE: crate::altrep::RBase = crate::altrep::RBase::Logical;
184
185 unsafe fn make_class(
186 class_name: *const i8,
187 pkg_name: *const i8,
188 ) -> crate::sys::altrep::R_altrep_class_t {
189 let cls = unsafe {
190 crate::sys::altrep::R_make_altlogical_class(
191 class_name,
192 pkg_name,
193 crate::altrep_dll_info(),
194 )
195 };
196 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
197 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
198 }
199
200 unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
201 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
202 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
203 unsafe { crate::altrep_bridge::install_lgl::<Self>(cls) };
204 }
205}
206
207impl<const N: usize> crate::altrep_traits::Altrep for [String; N] {
209 const GUARD: crate::altrep_traits::AltrepGuard = crate::altrep_traits::AltrepGuard::RUnwind;
210
211 fn length(x: crate::SEXP) -> crate::R_xlen_t {
212 let data =
213 unsafe { <[String; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
214 crate::altrep_data::AltrepLen::len(data) as crate::R_xlen_t
215 }
216}
217
218impl<const N: usize> crate::altrep_traits::AltVec for [String; N] {}
219
220impl<const N: usize> crate::altrep_traits::AltString for [String; N] {
221 fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> crate::SEXP {
222 let data =
223 unsafe { <[String; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
224 match <[String; N] as crate::altrep_data::AltStringData>::elt(data, i.max(0) as usize) {
225 Some(s) => unsafe { super::checked_mkchar(s) },
226 None => crate::SEXP::na_string(),
227 }
228 }
229}
230
231impl<const N: usize> crate::altrep_data::InferBase for [String; N] {
232 const BASE: crate::altrep::RBase = crate::altrep::RBase::String;
233
234 unsafe fn make_class(
235 class_name: *const i8,
236 pkg_name: *const i8,
237 ) -> crate::sys::altrep::R_altrep_class_t {
238 let cls = unsafe {
239 crate::sys::altrep::R_make_altstring_class(
240 class_name,
241 pkg_name,
242 crate::altrep_dll_info(),
243 )
244 };
245 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
246 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
247 }
248
249 unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
250 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
251 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
252 unsafe { crate::altrep_bridge::install_str::<Self>(cls) };
253 }
254}
255