1#[inline]
21pub unsafe fn checked_mkchar(s: &str) -> crate::ffi::SEXP {
22 let _len = i32::try_from(s.len()).unwrap_or_else(|_| {
23 panic!(
24 "string length {} exceeds i32::MAX for Rf_mkCharLenCE",
25 s.len()
26 )
27 });
28 crate::ffi::SEXP::charsxp(s)
29}
30#[inline]
47pub unsafe fn altrep_region_buf<T>(buf: *mut T, len: usize) -> &'static mut [T] {
48 unsafe { std::slice::from_raw_parts_mut(buf, len) }
49}
50#[macro_export]
81macro_rules! impl_altinteger_from_data {
82 ($ty:ty) => {
83 $crate::__impl_altrep_base!($ty);
86 $crate::__impl_altvec_integer_dataptr!($ty);
87 $crate::__impl_altinteger_methods!($ty);
88 $crate::impl_inferbase_integer!($ty);
89 };
90 ($ty:ty, dataptr) => {
91 $crate::__impl_alt_from_data!(
92 $ty,
93 __impl_altinteger_methods,
94 impl_inferbase_integer,
95 dataptr(i32)
96 );
97 };
98 ($ty:ty, serialize) => {
99 $crate::__impl_altrep_base_with_serialize!($ty);
101 $crate::__impl_altvec_integer_dataptr!($ty);
102 $crate::__impl_altinteger_methods!($ty);
103 $crate::impl_inferbase_integer!($ty);
104 };
105 ($ty:ty, subset) => {
106 $crate::__impl_alt_from_data!(
107 $ty,
108 __impl_altinteger_methods,
109 impl_inferbase_integer,
110 subset
111 );
112 };
113 ($ty:ty, dataptr, serialize) => {
114 $crate::__impl_alt_from_data!(
115 $ty,
116 __impl_altinteger_methods,
117 impl_inferbase_integer,
118 dataptr(i32),
119 serialize
120 );
121 };
122 ($ty:ty, serialize, dataptr) => {
123 $crate::impl_altinteger_from_data!($ty, dataptr, serialize);
124 };
125 ($ty:ty, subset, serialize) => {
126 $crate::__impl_alt_from_data!(
127 $ty,
128 __impl_altinteger_methods,
129 impl_inferbase_integer,
130 subset,
131 serialize
132 );
133 };
134 ($ty:ty, serialize, subset) => {
135 $crate::impl_altinteger_from_data!($ty, subset, serialize);
136 };
137 ($ty:ty, materializing_dataptr) => {
139 $crate::__impl_altrep_base!($ty);
140 $crate::__impl_altvec_integer_dataptr!($ty);
141 $crate::__impl_altinteger_methods!($ty);
142 $crate::impl_inferbase_integer!($ty);
143 };
144 ($ty:ty, materializing_dataptr, serialize) => {
146 $crate::__impl_altrep_base_with_serialize!($ty);
147 $crate::__impl_altvec_integer_dataptr!($ty);
148 $crate::__impl_altinteger_methods!($ty);
149 $crate::impl_inferbase_integer!($ty);
150 };
151}
152
153#[macro_export]
155#[doc(hidden)]
156macro_rules! __impl_altrep_base {
157 ($ty:ty) => {
158 $crate::__impl_altrep_base!($ty, RUnwind);
159 };
160 ($ty:ty, $guard:ident) => {
161 impl $crate::altrep_traits::Altrep for $ty {
162 const GUARD: $crate::altrep_traits::AltrepGuard =
163 $crate::altrep_traits::AltrepGuard::$guard;
164
165 fn length(x: $crate::ffi::SEXP) -> $crate::ffi::R_xlen_t {
166 let data =
167 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
168 <$ty as $crate::altrep_data::AltrepLen>::len(data) as $crate::ffi::R_xlen_t
169 }
170 }
171 };
172}
173
174#[macro_export]
187#[doc(hidden)]
188macro_rules! __impl_altrep_base_with_serialize {
189 ($ty:ty) => {
190 $crate::__impl_altrep_base_with_serialize!($ty, RUnwind);
191 };
192 ($ty:ty, $guard:ident) => {
193 impl $crate::altrep_traits::Altrep for $ty {
194 const GUARD: $crate::altrep_traits::AltrepGuard =
195 $crate::altrep_traits::AltrepGuard::$guard;
196
197 fn length(x: $crate::ffi::SEXP) -> $crate::ffi::R_xlen_t {
198 let data =
199 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
200 <$ty as $crate::altrep_data::AltrepLen>::len(data) as $crate::ffi::R_xlen_t
201 }
202
203 const HAS_SERIALIZED_STATE: bool = true;
204
205 fn serialized_state(x: $crate::ffi::SEXP) -> $crate::ffi::SEXP {
206 let data =
207 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
208 <$ty as $crate::altrep_data::AltrepSerialize>::serialized_state(data)
209 }
210
211 const HAS_UNSERIALIZE: bool = true;
212
213 fn unserialize(
214 class: $crate::ffi::SEXP,
215 state: $crate::ffi::SEXP,
216 ) -> $crate::ffi::SEXP {
217 let Some(data) = <$ty as $crate::altrep_data::AltrepSerialize>::unserialize(state)
218 else {
219 panic!(
220 "ALTREP unserialize failed for {}",
221 core::any::type_name::<$ty>()
222 );
223 };
224
225 unsafe {
227 use $crate::externalptr::ExternalPtr;
228 use $crate::ffi::altrep::R_altrep_class_t;
229 use $crate::ffi::{Rf_protect_unchecked, Rf_unprotect_unchecked, SEXP};
230
231 let ext_ptr = ExternalPtr::new_unchecked(data);
232 let data1 = ext_ptr.as_sexp();
233 Rf_protect_unchecked(data1);
235 let cls = R_altrep_class_t::from_sexp(class);
236 let out = cls.new_altrep_unchecked(data1, SEXP::nil());
237 Rf_unprotect_unchecked(1);
238 out
239 }
240 }
241 }
242 };
243}
244
245#[macro_export]
253#[doc(hidden)]
254macro_rules! __impl_altvec_dataptr {
255 ($ty:ty, $elem:ty) => {
256 impl $crate::altrep_traits::AltVec for $ty {
257 const HAS_DATAPTR: bool = true;
258
259 fn dataptr(x: $crate::ffi::SEXP, writable: bool) -> *mut core::ffi::c_void {
260 unsafe {
262 let data2 = $crate::altrep_ext::AltrepSexpExt::altrep_data2(&x);
263 if !data2.is_null()
264 && $crate::ffi::SexpExt::type_of(&data2)
265 == <$elem as $crate::ffi::RNativeType>::SEXP_TYPE
266 {
267 return $crate::ffi::DATAPTR_RO(data2).cast_mut();
268 }
269 }
270
271 let direct = if writable {
273 let d = unsafe {
274 <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
275 };
276 <$ty as $crate::altrep_data::AltrepDataptr<$elem>>::dataptr(d, true)
277 .map(|p| p.cast::<core::ffi::c_void>())
278 } else {
279 let d = unsafe {
282 <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
283 };
284 let ro = <$ty as $crate::altrep_data::AltrepDataptr<$elem>>::dataptr_or_null(d);
285 if let Some(p) = ro {
286 return p.cast_mut().cast::<core::ffi::c_void>();
287 }
288 let d = unsafe {
290 <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
291 };
292 <$ty as $crate::altrep_data::AltrepDataptr<$elem>>::dataptr(d, false)
293 .map(|p| p.cast::<core::ffi::c_void>())
294 };
295
296 if let Some(p) = direct {
297 return p;
298 }
299
300 unsafe { $crate::altrep_data::materialize_altrep_data2::<$elem>(x) }
304 }
305
306 const HAS_DATAPTR_OR_NULL: bool = true;
307
308 fn dataptr_or_null(x: $crate::ffi::SEXP) -> *const core::ffi::c_void {
309 unsafe {
311 let data2 = $crate::altrep_ext::AltrepSexpExt::altrep_data2(&x);
312 if !data2.is_null()
313 && $crate::ffi::SexpExt::type_of(&data2)
314 == <$elem as $crate::ffi::RNativeType>::SEXP_TYPE
315 {
316 return $crate::ffi::DATAPTR_RO(data2);
317 }
318 }
319 let d =
320 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
321 <$ty as $crate::altrep_data::AltrepDataptr<$elem>>::dataptr_or_null(d)
322 .map(|p| p.cast::<core::ffi::c_void>())
323 .unwrap_or(core::ptr::null())
324 }
325 }
326 };
327}
328
329#[macro_export]
336#[doc(hidden)]
337macro_rules! __impl_altvec_string_dataptr {
338 ($ty:ty) => {
339 impl $crate::altrep_traits::AltVec for $ty {
340 const HAS_DATAPTR: bool = true;
341
342 fn dataptr(x: $crate::ffi::SEXP, _writable: bool) -> *mut core::ffi::c_void {
343 unsafe {
344 let n = <$ty as $crate::altrep_traits::Altrep>::length(x);
345
346 let mut data2 = $crate::altrep_ext::AltrepSexpExt::altrep_data2(&x);
348 let fresh_alloc = data2.is_null()
349 || $crate::ffi::SexpExt::type_of(&data2) != $crate::ffi::SEXPTYPE::STRSXP;
350 if fresh_alloc {
351 data2 = $crate::ffi::Rf_protect($crate::ffi::Rf_allocVector(
355 $crate::ffi::SEXPTYPE::STRSXP,
356 n,
357 ));
358 for j in 0..n {
359 $crate::ffi::SexpExt::set_string_elt(
360 &data2,
361 j,
362 $crate::ffi::SEXP::na_string(),
363 );
364 }
365 $crate::altrep_ext::AltrepSexpExt::set_altrep_data2(&x, data2);
366 $crate::ffi::Rf_unprotect(1);
367 }
368
369 for i in 0..n {
373 let cached = $crate::ffi::SexpExt::string_elt(&data2, i);
374 if cached != $crate::ffi::SEXP::na_string() {
375 continue; }
377 let elt = <$ty as $crate::altrep_traits::AltString>::elt(x, i);
379 $crate::ffi::SexpExt::set_string_elt(&data2, i, elt);
380 }
381
382 $crate::ffi::DATAPTR_RO(data2).cast_mut()
383 }
384 }
385
386 const HAS_DATAPTR_OR_NULL: bool = true;
387
388 fn dataptr_or_null(x: $crate::ffi::SEXP) -> *const core::ffi::c_void {
389 let _ = x;
396 core::ptr::null()
397 }
398 }
399 };
400}
401
402#[macro_export]
408#[doc(hidden)]
409macro_rules! __impl_altvec_logical_dataptr {
410 ($ty:ty) => {
411 impl $crate::altrep_data::AltrepDataptr<$crate::ffi::RLogical> for $ty {
412 fn dataptr(&mut self, _writable: bool) -> Option<*mut $crate::ffi::RLogical> {
413 None
414 }
415 }
416 $crate::__impl_altvec_dataptr!($ty, $crate::ffi::RLogical);
417 };
418}
419
420#[macro_export]
427#[doc(hidden)]
428macro_rules! __impl_altvec_integer_dataptr {
429 ($ty:ty) => {
430 impl $crate::altrep_data::AltrepDataptr<i32> for $ty {
431 fn dataptr(&mut self, _writable: bool) -> Option<*mut i32> {
432 None
433 }
434 }
435 $crate::__impl_altvec_dataptr!($ty, i32);
436 };
437}
438
439#[macro_export]
441#[doc(hidden)]
442macro_rules! __impl_altvec_real_dataptr {
443 ($ty:ty) => {
444 impl $crate::altrep_data::AltrepDataptr<f64> for $ty {
445 fn dataptr(&mut self, _writable: bool) -> Option<*mut f64> {
446 None
447 }
448 }
449 $crate::__impl_altvec_dataptr!($ty, f64);
450 };
451}
452
453#[macro_export]
455#[doc(hidden)]
456macro_rules! __impl_altvec_raw_dataptr {
457 ($ty:ty) => {
458 impl $crate::altrep_data::AltrepDataptr<u8> for $ty {
459 fn dataptr(&mut self, _writable: bool) -> Option<*mut u8> {
460 None
461 }
462 }
463 $crate::__impl_altvec_dataptr!($ty, u8);
464 };
465}
466
467#[macro_export]
469#[doc(hidden)]
470macro_rules! __impl_altvec_complex_dataptr {
471 ($ty:ty) => {
472 impl $crate::altrep_data::AltrepDataptr<$crate::ffi::Rcomplex> for $ty {
473 fn dataptr(&mut self, _writable: bool) -> Option<*mut $crate::ffi::Rcomplex> {
474 None
475 }
476 }
477 $crate::__impl_altvec_dataptr!($ty, $crate::ffi::Rcomplex);
478 };
479}
480
481#[macro_export]
483#[doc(hidden)]
484macro_rules! __impl_altvec_extract_subset {
485 ($ty:ty) => {
486 impl $crate::altrep_traits::AltVec for $ty {
487 const HAS_EXTRACT_SUBSET: bool = true;
488
489 fn extract_subset(
490 x: $crate::ffi::SEXP,
491 indx: $crate::ffi::SEXP,
492 _call: $crate::ffi::SEXP,
493 ) -> $crate::ffi::SEXP {
494 if $crate::ffi::SexpExt::type_of(&indx) != $crate::ffi::SEXPTYPE::INTSXP {
497 return core::ptr::null_mut();
498 }
499
500 let indices = unsafe { $crate::ffi::SexpExt::as_slice::<i32>(&indx) };
502
503 let data =
504 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
505 <$ty as $crate::altrep_data::AltrepExtractSubset>::extract_subset(data, indices)
506 .unwrap_or($crate::ffi::SEXP::nil())
507 }
508 }
509 };
510}
511#[macro_export]
524#[doc(hidden)]
525macro_rules! __impl_alt_elt {
526 ($ty:ty, $trait:path, $elem:ty, $na:expr) => {
527 const HAS_ELT: bool = true;
528
529 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> $elem {
530 let data =
531 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
532 <$ty as $trait>::elt(data, i.max(0) as usize)
533 }
534 };
535}
536
537#[macro_export]
542#[doc(hidden)]
543macro_rules! __impl_alt_get_region {
544 ($ty:ty, $trait:path, $buf_ty:ty) => {
545 const HAS_GET_REGION: bool = true;
546
547 fn get_region(
548 x: $crate::ffi::SEXP,
549 start: $crate::ffi::R_xlen_t,
550 len: $crate::ffi::R_xlen_t,
551 buf: &mut [$buf_ty],
552 ) -> $crate::ffi::R_xlen_t {
553 if start < 0 || len <= 0 {
554 return 0;
555 }
556 let data =
557 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
558 let len = len as usize;
559 <$ty as $trait>::get_region(data, start as usize, len, buf) as $crate::ffi::R_xlen_t
560 }
561 };
562}
563
564#[macro_export]
569#[doc(hidden)]
570macro_rules! __impl_alt_is_sorted {
571 ($ty:ty, $trait:path) => {
572 const HAS_IS_SORTED: bool = true;
573
574 fn is_sorted(x: $crate::ffi::SEXP) -> i32 {
575 let data =
576 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
577 <$ty as $trait>::is_sorted(data)
578 .map(|s| s.to_r_int())
579 .unwrap_or(i32::MIN)
580 }
581 };
582}
583
584#[macro_export]
589#[doc(hidden)]
590macro_rules! __impl_alt_no_na {
591 ($ty:ty, $trait:path) => {
592 const HAS_NO_NA: bool = true;
593
594 fn no_na(x: $crate::ffi::SEXP) -> i32 {
595 let data =
596 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
597 <$ty as $trait>::no_na(data)
598 .map(|b| if b { 1 } else { 0 })
599 .unwrap_or(0)
600 }
601 };
602}
603#[macro_export]
613#[doc(hidden)]
614macro_rules! __impl_alt_from_data {
615 ($ty:ty, $methods:ident, $inferbase:ident) => {
617 $crate::__impl_altrep_base!($ty);
618 impl $crate::altrep_traits::AltVec for $ty {}
619 $crate::$methods!($ty);
620 $crate::$inferbase!($ty);
621 };
622 ($ty:ty, $methods:ident, $inferbase:ident, @guard $guard:ident) => {
624 $crate::__impl_altrep_base!($ty, $guard);
625 impl $crate::altrep_traits::AltVec for $ty {}
626 $crate::$methods!($ty);
627 $crate::$inferbase!($ty);
628 };
629 ($ty:ty, $methods:ident, $inferbase:ident, dataptr($elem:ty)) => {
631 $crate::__impl_altrep_base!($ty);
632 $crate::__impl_altvec_dataptr!($ty, $elem);
633 $crate::$methods!($ty);
634 $crate::$inferbase!($ty);
635 };
636 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr) => {
638 $crate::__impl_altrep_base!($ty);
639 $crate::__impl_altvec_string_dataptr!($ty);
640 $crate::$methods!($ty);
641 $crate::$inferbase!($ty);
642 };
643 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr, @guard $guard:ident) => {
645 $crate::__impl_altrep_base!($ty, $guard);
646 $crate::__impl_altvec_string_dataptr!($ty);
647 $crate::$methods!($ty);
648 $crate::$inferbase!($ty);
649 };
650 ($ty:ty, $methods:ident, $inferbase:ident, serialize) => {
652 $crate::__impl_altrep_base_with_serialize!($ty);
653 impl $crate::altrep_traits::AltVec for $ty {}
654 $crate::$methods!($ty);
655 $crate::$inferbase!($ty);
656 };
657 ($ty:ty, $methods:ident, $inferbase:ident, serialize, @guard $guard:ident) => {
659 $crate::__impl_altrep_base_with_serialize!($ty, $guard);
660 impl $crate::altrep_traits::AltVec for $ty {}
661 $crate::$methods!($ty);
662 $crate::$inferbase!($ty);
663 };
664 ($ty:ty, $methods:ident, $inferbase:ident, subset) => {
666 $crate::__impl_altrep_base!($ty);
667 $crate::__impl_altvec_extract_subset!($ty);
668 $crate::$methods!($ty);
669 $crate::$inferbase!($ty);
670 };
671 ($ty:ty, $methods:ident, $inferbase:ident, dataptr($elem:ty), serialize) => {
673 $crate::__impl_altrep_base_with_serialize!($ty);
674 $crate::__impl_altvec_dataptr!($ty, $elem);
675 $crate::$methods!($ty);
676 $crate::$inferbase!($ty);
677 };
678 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr, serialize) => {
680 $crate::__impl_altrep_base_with_serialize!($ty);
681 $crate::__impl_altvec_string_dataptr!($ty);
682 $crate::$methods!($ty);
683 $crate::$inferbase!($ty);
684 };
685 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr, serialize, @guard $guard:ident) => {
687 $crate::__impl_altrep_base_with_serialize!($ty, $guard);
688 $crate::__impl_altvec_string_dataptr!($ty);
689 $crate::$methods!($ty);
690 $crate::$inferbase!($ty);
691 };
692 ($ty:ty, $methods:ident, $inferbase:ident, subset, serialize) => {
694 $crate::__impl_altrep_base_with_serialize!($ty);
695 $crate::__impl_altvec_extract_subset!($ty);
696 $crate::$methods!($ty);
697 $crate::$inferbase!($ty);
698 };
699}
700#[macro_export]
706#[doc(hidden)]
707macro_rules! __impl_altinteger_methods {
708 ($ty:ty) => {
709 impl $crate::altrep_traits::AltInteger for $ty {
710 $crate::__impl_alt_elt!($ty, $crate::altrep_data::AltIntegerData, i32, i32::MIN);
711 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltIntegerData, i32);
712 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltIntegerData);
713 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltIntegerData);
714
715 const HAS_SUM: bool = true;
716
717 fn sum(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
719 let data =
720 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
721 match <$ty as $crate::altrep_data::AltIntegerData>::sum(data, narm) {
722 Some(s) => {
723 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
724 $crate::ffi::SEXP::scalar_integer(s as i32)
725 } else {
726 $crate::ffi::SEXP::scalar_real(s as f64)
727 }
728 }
729 None => $crate::ffi::SEXP::null(),
730 }
731 }
732
733 const HAS_MIN: bool = true;
734
735 fn min(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
736 let data =
737 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
738 <$ty as $crate::altrep_data::AltIntegerData>::min(data, narm)
739 .map(|m| $crate::ffi::SEXP::scalar_integer(m))
740 .unwrap_or($crate::ffi::SEXP::null())
741 }
742
743 const HAS_MAX: bool = true;
744
745 fn max(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
746 let data =
747 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
748 <$ty as $crate::altrep_data::AltIntegerData>::max(data, narm)
749 .map(|m| $crate::ffi::SEXP::scalar_integer(m))
750 .unwrap_or($crate::ffi::SEXP::null())
751 }
752 }
753 };
754}
755
756#[macro_export]
778macro_rules! impl_altreal_from_data {
779 ($ty:ty) => {
780 $crate::__impl_altrep_base!($ty);
781 $crate::__impl_altvec_real_dataptr!($ty);
782 $crate::__impl_altreal_methods!($ty);
783 $crate::impl_inferbase_real!($ty);
784 };
785 ($ty:ty, dataptr) => {
786 $crate::__impl_alt_from_data!(
787 $ty,
788 __impl_altreal_methods,
789 impl_inferbase_real,
790 dataptr(f64)
791 );
792 };
793 ($ty:ty, serialize) => {
794 $crate::__impl_altrep_base_with_serialize!($ty);
795 $crate::__impl_altvec_real_dataptr!($ty);
796 $crate::__impl_altreal_methods!($ty);
797 $crate::impl_inferbase_real!($ty);
798 };
799 ($ty:ty, dataptr, serialize) => {
800 $crate::__impl_alt_from_data!(
801 $ty,
802 __impl_altreal_methods,
803 impl_inferbase_real,
804 dataptr(f64),
805 serialize
806 );
807 };
808 ($ty:ty, serialize, dataptr) => {
809 $crate::impl_altreal_from_data!($ty, dataptr, serialize);
810 };
811 ($ty:ty, subset) => {
812 $crate::__impl_alt_from_data!($ty, __impl_altreal_methods, impl_inferbase_real, subset);
813 };
814 ($ty:ty, subset, serialize) => {
815 $crate::__impl_alt_from_data!(
816 $ty,
817 __impl_altreal_methods,
818 impl_inferbase_real,
819 subset,
820 serialize
821 );
822 };
823 ($ty:ty, serialize, subset) => {
824 $crate::impl_altreal_from_data!($ty, subset, serialize);
825 };
826 ($ty:ty, materializing_dataptr) => {
828 $crate::__impl_altrep_base!($ty);
829 $crate::__impl_altvec_real_dataptr!($ty);
830 $crate::__impl_altreal_methods!($ty);
831 $crate::impl_inferbase_real!($ty);
832 };
833 ($ty:ty, materializing_dataptr, serialize) => {
835 $crate::__impl_altrep_base_with_serialize!($ty);
836 $crate::__impl_altvec_real_dataptr!($ty);
837 $crate::__impl_altreal_methods!($ty);
838 $crate::impl_inferbase_real!($ty);
839 };
840}
841
842#[macro_export]
844#[doc(hidden)]
845macro_rules! __impl_altreal_methods {
846 ($ty:ty) => {
847 impl $crate::altrep_traits::AltReal for $ty {
848 $crate::__impl_alt_elt!($ty, $crate::altrep_data::AltRealData, f64, f64::NAN);
849 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltRealData, f64);
850 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltRealData);
851 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltRealData);
852
853 const HAS_SUM: bool = true;
854
855 fn sum(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
857 let data =
858 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
859 <$ty as $crate::altrep_data::AltRealData>::sum(data, narm)
860 .map(|s| $crate::ffi::SEXP::scalar_real(s))
861 .unwrap_or($crate::ffi::SEXP::null())
862 }
863
864 const HAS_MIN: bool = true;
865
866 fn min(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
867 let data =
868 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
869 <$ty as $crate::altrep_data::AltRealData>::min(data, narm)
870 .map(|m| $crate::ffi::SEXP::scalar_real(m))
871 .unwrap_or($crate::ffi::SEXP::null())
872 }
873
874 const HAS_MAX: bool = true;
875
876 fn max(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
877 let data =
878 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
879 <$ty as $crate::altrep_data::AltRealData>::max(data, narm)
880 .map(|m| $crate::ffi::SEXP::scalar_real(m))
881 .unwrap_or($crate::ffi::SEXP::null())
882 }
883 }
884 };
885}
886
887#[macro_export]
909macro_rules! impl_altlogical_from_data {
910 ($ty:ty) => {
911 $crate::__impl_altrep_base!($ty);
912 $crate::__impl_altvec_logical_dataptr!($ty);
913 $crate::__impl_altlogical_methods!($ty);
914 $crate::impl_inferbase_logical!($ty);
915 };
916 ($ty:ty, dataptr) => {
917 $crate::__impl_alt_from_data!(
918 $ty,
919 __impl_altlogical_methods,
920 impl_inferbase_logical,
921 dataptr(i32)
922 );
923 };
924 ($ty:ty, serialize) => {
925 $crate::__impl_altrep_base_with_serialize!($ty);
926 $crate::__impl_altvec_logical_dataptr!($ty);
927 $crate::__impl_altlogical_methods!($ty);
928 $crate::impl_inferbase_logical!($ty);
929 };
930 ($ty:ty, dataptr, serialize) => {
931 $crate::__impl_alt_from_data!(
932 $ty,
933 __impl_altlogical_methods,
934 impl_inferbase_logical,
935 dataptr(i32),
936 serialize
937 );
938 };
939 ($ty:ty, serialize, dataptr) => {
940 $crate::impl_altlogical_from_data!($ty, dataptr, serialize);
941 };
942 ($ty:ty, subset) => {
943 $crate::__impl_alt_from_data!(
944 $ty,
945 __impl_altlogical_methods,
946 impl_inferbase_logical,
947 subset
948 );
949 };
950 ($ty:ty, subset, serialize) => {
951 $crate::__impl_alt_from_data!(
952 $ty,
953 __impl_altlogical_methods,
954 impl_inferbase_logical,
955 subset,
956 serialize
957 );
958 };
959 ($ty:ty, serialize, subset) => {
960 $crate::impl_altlogical_from_data!($ty, subset, serialize);
961 };
962 ($ty:ty, materializing_dataptr) => {
964 $crate::__impl_altrep_base!($ty);
965 $crate::__impl_altvec_logical_dataptr!($ty);
966 $crate::__impl_altlogical_methods!($ty);
967 $crate::impl_inferbase_logical!($ty);
968 };
969 ($ty:ty, materializing_dataptr, serialize) => {
971 $crate::__impl_altrep_base_with_serialize!($ty);
972 $crate::__impl_altvec_logical_dataptr!($ty);
973 $crate::__impl_altlogical_methods!($ty);
974 $crate::impl_inferbase_logical!($ty);
975 };
976}
977
978#[macro_export]
980#[doc(hidden)]
981macro_rules! __impl_altlogical_methods {
982 ($ty:ty) => {
983 impl $crate::altrep_traits::AltLogical for $ty {
984 const HAS_ELT: bool = true;
986
987 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> i32 {
988 let data =
989 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
990 <$ty as $crate::altrep_data::AltLogicalData>::elt(data, i.max(0) as usize)
991 .to_r_int()
992 }
993
994 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltLogicalData, i32);
995 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltLogicalData);
996 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltLogicalData);
997
998 const HAS_SUM: bool = true;
999
1000 fn sum(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
1002 let data =
1003 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1004 match <$ty as $crate::altrep_data::AltLogicalData>::sum(data, narm) {
1005 Some(s) => {
1006 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
1007 $crate::ffi::SEXP::scalar_integer(s as i32)
1008 } else {
1009 $crate::ffi::SEXP::scalar_real(s as f64)
1010 }
1011 }
1012 None => $crate::ffi::SEXP::null(),
1013 }
1014 }
1015 }
1016 };
1017}
1018
1019#[macro_export]
1041macro_rules! impl_altraw_from_data {
1042 ($ty:ty) => {
1043 $crate::__impl_altrep_base!($ty);
1044 $crate::__impl_altvec_raw_dataptr!($ty);
1045 $crate::__impl_altraw_methods!($ty);
1046 $crate::impl_inferbase_raw!($ty);
1047 };
1048 ($ty:ty, dataptr) => {
1049 $crate::__impl_alt_from_data!($ty, __impl_altraw_methods, impl_inferbase_raw, dataptr(u8));
1050 };
1051 ($ty:ty, serialize) => {
1052 $crate::__impl_altrep_base_with_serialize!($ty);
1053 $crate::__impl_altvec_raw_dataptr!($ty);
1054 $crate::__impl_altraw_methods!($ty);
1055 $crate::impl_inferbase_raw!($ty);
1056 };
1057 ($ty:ty, dataptr, serialize) => {
1058 $crate::__impl_alt_from_data!(
1059 $ty,
1060 __impl_altraw_methods,
1061 impl_inferbase_raw,
1062 dataptr(u8),
1063 serialize
1064 );
1065 };
1066 ($ty:ty, serialize, dataptr) => {
1067 $crate::impl_altraw_from_data!($ty, dataptr, serialize);
1068 };
1069 ($ty:ty, subset) => {
1070 $crate::__impl_alt_from_data!($ty, __impl_altraw_methods, impl_inferbase_raw, subset);
1071 };
1072 ($ty:ty, subset, serialize) => {
1073 $crate::__impl_alt_from_data!(
1074 $ty,
1075 __impl_altraw_methods,
1076 impl_inferbase_raw,
1077 subset,
1078 serialize
1079 );
1080 };
1081 ($ty:ty, serialize, subset) => {
1082 $crate::impl_altraw_from_data!($ty, subset, serialize);
1083 };
1084}
1085
1086#[macro_export]
1088#[doc(hidden)]
1089macro_rules! __impl_altraw_methods {
1090 ($ty:ty) => {
1091 impl $crate::altrep_traits::AltRaw for $ty {
1092 $crate::__impl_alt_elt!($ty, $crate::altrep_data::AltRawData, u8, 0);
1093 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltRawData, u8);
1094 }
1095 };
1096}
1097
1098#[macro_export]
1120macro_rules! impl_altstring_from_data {
1121 ($ty:ty) => {
1122 $crate::__impl_altrep_base!($ty);
1123 $crate::__impl_altvec_string_dataptr!($ty);
1124 $crate::__impl_altstring_methods!($ty);
1125 $crate::impl_inferbase_string!($ty);
1126 };
1127 ($ty:ty, dataptr) => {
1128 $crate::__impl_alt_from_data!(
1129 $ty,
1130 __impl_altstring_methods,
1131 impl_inferbase_string,
1132 string_dataptr
1133 );
1134 };
1135 ($ty:ty, serialize) => {
1136 $crate::__impl_altrep_base_with_serialize!($ty);
1137 $crate::__impl_altvec_string_dataptr!($ty);
1138 $crate::__impl_altstring_methods!($ty);
1139 $crate::impl_inferbase_string!($ty);
1140 };
1141 ($ty:ty, dataptr, serialize) => {
1142 $crate::__impl_alt_from_data!(
1143 $ty,
1144 __impl_altstring_methods,
1145 impl_inferbase_string,
1146 string_dataptr,
1147 serialize
1148 );
1149 };
1150 ($ty:ty, subset) => {
1151 $crate::__impl_alt_from_data!($ty, __impl_altstring_methods, impl_inferbase_string, subset);
1152 };
1153 ($ty:ty, subset, serialize) => {
1154 $crate::__impl_alt_from_data!(
1155 $ty,
1156 __impl_altstring_methods,
1157 impl_inferbase_string,
1158 subset,
1159 serialize
1160 );
1161 };
1162 ($ty:ty, serialize, subset) => {
1163 $crate::impl_altstring_from_data!($ty, subset, serialize);
1164 };
1165}
1166
1167#[macro_export]
1169#[doc(hidden)]
1170macro_rules! __impl_altstring_methods {
1171 ($ty:ty) => {
1172 impl $crate::altrep_traits::AltString for $ty {
1173 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> $crate::ffi::SEXP {
1183 unsafe {
1184 let idx = i.max(0) as usize;
1185
1186 let mut data2 = $crate::altrep_ext::AltrepSexpExt::altrep_data2(&x);
1188 if data2.is_null()
1189 || $crate::ffi::SexpExt::type_of(&data2) != $crate::ffi::SEXPTYPE::STRSXP
1190 {
1191 let n = <$ty as $crate::altrep_traits::Altrep>::length(x);
1192 data2 = $crate::ffi::Rf_protect($crate::ffi::Rf_allocVector(
1195 $crate::ffi::SEXPTYPE::STRSXP,
1196 n,
1197 ));
1198 for j in 0..n {
1199 $crate::ffi::SexpExt::set_string_elt(
1200 &data2,
1201 j,
1202 $crate::ffi::SEXP::na_string(),
1203 );
1204 }
1205 $crate::altrep_ext::AltrepSexpExt::set_altrep_data2(&x, data2);
1206 $crate::ffi::Rf_unprotect(1);
1207 }
1208
1209 let cached = $crate::ffi::SexpExt::string_elt(&data2, i);
1211 if cached != $crate::ffi::SEXP::na_string() {
1212 return cached;
1213 }
1214
1215 let data = <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x);
1217 match <$ty as $crate::altrep_data::AltStringData>::elt(data, idx) {
1218 Some(s) => {
1219 let charsxp = $crate::altrep_impl::checked_mkchar(s);
1220 $crate::ffi::SexpExt::set_string_elt(&data2, i, charsxp);
1221 charsxp
1222 }
1223 None => $crate::ffi::SEXP::na_string(),
1224 }
1225 }
1226 }
1227
1228 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltStringData);
1229 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltStringData);
1230 }
1231 };
1232}
1233
1234#[macro_export]
1236macro_rules! impl_altlist_from_data {
1237 ($ty:ty) => {
1238 $crate::impl_altlist_from_data!($ty, RUnwind);
1239 };
1240 ($ty:ty, $guard:ident) => {
1241 impl $crate::altrep_traits::Altrep for $ty {
1242 const GUARD: $crate::altrep_traits::AltrepGuard =
1243 $crate::altrep_traits::AltrepGuard::$guard;
1244
1245 fn length(x: $crate::ffi::SEXP) -> $crate::ffi::R_xlen_t {
1246 let data =
1247 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1248 <$ty as $crate::altrep_data::AltrepLen>::len(data) as $crate::ffi::R_xlen_t
1249 }
1250 }
1251
1252 impl $crate::altrep_traits::AltVec for $ty {}
1253
1254 impl $crate::altrep_traits::AltList for $ty {
1255 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> $crate::ffi::SEXP {
1256 let data =
1257 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1258 <$ty as $crate::altrep_data::AltListData>::elt(data, i.max(0) as usize)
1259 }
1260 }
1261
1262 $crate::impl_inferbase_list!($ty);
1263 };
1264}
1265
1266#[macro_export]
1268#[doc(hidden)]
1269macro_rules! __impl_altcomplex_methods {
1270 ($ty:ty) => {
1271 impl $crate::altrep_traits::AltComplex for $ty {
1272 $crate::__impl_alt_elt!(
1273 $ty,
1274 $crate::altrep_data::AltComplexData,
1275 $crate::ffi::Rcomplex,
1276 $crate::ffi::Rcomplex {
1277 r: f64::NAN,
1278 i: f64::NAN
1279 }
1280 );
1281 $crate::__impl_alt_get_region!(
1282 $ty,
1283 $crate::altrep_data::AltComplexData,
1284 $crate::ffi::Rcomplex
1285 );
1286 }
1287 };
1288}
1289
1290#[macro_export]
1297macro_rules! impl_altcomplex_from_data {
1298 ($ty:ty) => {
1299 $crate::__impl_altrep_base!($ty);
1300 $crate::__impl_altvec_complex_dataptr!($ty);
1301 $crate::__impl_altcomplex_methods!($ty);
1302 $crate::impl_inferbase_complex!($ty);
1303 };
1304 ($ty:ty, dataptr) => {
1305 $crate::__impl_alt_from_data!(
1306 $ty,
1307 __impl_altcomplex_methods,
1308 impl_inferbase_complex,
1309 dataptr($crate::ffi::Rcomplex)
1310 );
1311 };
1312 ($ty:ty, serialize) => {
1313 $crate::__impl_altrep_base_with_serialize!($ty);
1314 $crate::__impl_altvec_complex_dataptr!($ty);
1315 $crate::__impl_altcomplex_methods!($ty);
1316 $crate::impl_inferbase_complex!($ty);
1317 };
1318 ($ty:ty, subset) => {
1319 $crate::__impl_alt_from_data!(
1320 $ty,
1321 __impl_altcomplex_methods,
1322 impl_inferbase_complex,
1323 subset
1324 );
1325 };
1326 ($ty:ty, dataptr, serialize) => {
1327 $crate::__impl_alt_from_data!(
1328 $ty,
1329 __impl_altcomplex_methods,
1330 impl_inferbase_complex,
1331 dataptr($crate::ffi::Rcomplex),
1332 serialize
1333 );
1334 };
1335 ($ty:ty, serialize, dataptr) => {
1336 $crate::impl_altcomplex_from_data!($ty, dataptr, serialize);
1337 };
1338 ($ty:ty, subset, serialize) => {
1339 $crate::__impl_alt_from_data!(
1340 $ty,
1341 __impl_altcomplex_methods,
1342 impl_inferbase_complex,
1343 subset,
1344 serialize
1345 );
1346 };
1347 ($ty:ty, serialize, subset) => {
1348 $crate::impl_altcomplex_from_data!($ty, subset, serialize);
1349 };
1350}
1351impl_altinteger_from_data!(Vec<i32>, dataptr, serialize);
1362impl_altinteger_from_data!(std::ops::Range<i32>, materializing_dataptr, serialize);
1363impl_altinteger_from_data!(std::ops::Range<i64>, materializing_dataptr, serialize);
1364
1365impl_altreal_from_data!(Vec<f64>, dataptr, serialize);
1367impl_altreal_from_data!(std::ops::Range<f64>, materializing_dataptr, serialize);
1368
1369impl_altlogical_from_data!(Vec<bool>, materializing_dataptr, serialize);
1371
1372impl_altraw_from_data!(Vec<u8>, dataptr, serialize);
1374
1375impl_altstring_from_data!(Vec<String>, dataptr, serialize);
1377impl_altstring_from_data!(Vec<Option<String>>, dataptr, serialize);
1379impl_altstring_from_data!(Vec<std::borrow::Cow<'static, str>>, dataptr, serialize);
1383impl_altstring_from_data!(
1384 Vec<Option<std::borrow::Cow<'static, str>>>,
1385 dataptr,
1386 serialize
1387);
1388
1389impl_altcomplex_from_data!(Vec<crate::ffi::Rcomplex>, dataptr, serialize);
1391impl_altinteger_from_data!(Box<[i32]>, dataptr, serialize);
1399impl_altreal_from_data!(Box<[f64]>, dataptr, serialize);
1400impl_altlogical_from_data!(Box<[bool]>, materializing_dataptr, serialize);
1401impl_altraw_from_data!(Box<[u8]>, dataptr, serialize);
1402impl_altstring_from_data!(Box<[String]>, dataptr, serialize);
1403impl_altcomplex_from_data!(Box<[crate::ffi::Rcomplex]>, dataptr, serialize);
1404
1405impl_altinteger_from_data!(std::borrow::Cow<'static, [i32]>, dataptr, serialize);
1408impl_altreal_from_data!(std::borrow::Cow<'static, [f64]>, dataptr, serialize);
1409impl_altraw_from_data!(std::borrow::Cow<'static, [u8]>, dataptr, serialize);
1410impl_altcomplex_from_data!(
1411 std::borrow::Cow<'static, [crate::ffi::Rcomplex]>,
1412 dataptr,
1413 serialize
1414);
1415
1416pub(crate) fn register_builtin_altrep_classes() {
1423 use crate::altrep::RegisterAltrep;
1424
1425 Vec::<i32>::get_or_init_class();
1427 Vec::<f64>::get_or_init_class();
1428 Vec::<bool>::get_or_init_class();
1429 Vec::<u8>::get_or_init_class();
1430 Vec::<String>::get_or_init_class();
1431 Vec::<Option<String>>::get_or_init_class();
1432 Vec::<crate::ffi::Rcomplex>::get_or_init_class();
1433
1434 Vec::<std::borrow::Cow<'static, str>>::get_or_init_class();
1436 Vec::<Option<std::borrow::Cow<'static, str>>>::get_or_init_class();
1437
1438 Box::<[i32]>::get_or_init_class();
1440 Box::<[f64]>::get_or_init_class();
1441 Box::<[bool]>::get_or_init_class();
1442 Box::<[u8]>::get_or_init_class();
1443 Box::<[String]>::get_or_init_class();
1444 Box::<[crate::ffi::Rcomplex]>::get_or_init_class();
1445
1446 std::borrow::Cow::<'static, [i32]>::get_or_init_class();
1448 std::borrow::Cow::<'static, [f64]>::get_or_init_class();
1449 std::borrow::Cow::<'static, [u8]>::get_or_init_class();
1450 std::borrow::Cow::<'static, [crate::ffi::Rcomplex]>::get_or_init_class();
1451
1452 std::ops::Range::<i32>::get_or_init_class();
1454 std::ops::Range::<i64>::get_or_init_class();
1455 std::ops::Range::<f64>::get_or_init_class();
1456}
1457
1458#[cfg(feature = "arrow")]
1460pub(crate) fn register_arrow_altrep_classes() {
1461 use crate::altrep::RegisterAltrep;
1462 use crate::optionals::arrow_impl::*;
1463
1464 Float64Array::get_or_init_class();
1465 Int32Array::get_or_init_class();
1466 UInt8Array::get_or_init_class();
1467 BooleanArray::get_or_init_class();
1468 StringArray::get_or_init_class();
1469}
1470
1471macro_rules! impl_altrep_array_numeric {
1483 (
1484 elem = $elem:ty,
1485 data_trait = $data_trait:path,
1486 alt_trait = $alt_trait:path,
1487 rbase = $rbase:expr,
1488 make_class_fn = $make_class_fn:path,
1489 install_family_fn = $install_family_fn:ident
1490 $(, extra { $($extra:tt)* } )?
1491 $(,)?
1492 ) => {
1493 impl<const N: usize> crate::altrep_traits::Altrep for [$elem; N] {
1494 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1495 let data = unsafe {
1496 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1497 };
1498 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1499 }
1500 }
1501
1502 impl<const N: usize> crate::altrep_traits::AltVec for [$elem; N] {
1503 const HAS_DATAPTR: bool = true;
1504
1505 fn dataptr(x: crate::ffi::SEXP, _writable: bool) -> *mut core::ffi::c_void {
1506 let data = unsafe {
1507 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
1508 };
1509 data.as_mut_ptr().cast::<core::ffi::c_void>()
1510 }
1511 }
1512
1513 impl<const N: usize> $alt_trait for [$elem; N] {
1514 const HAS_ELT: bool = true;
1515
1516 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> $elem {
1517 let data = unsafe {
1518 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1519 };
1520 <[$elem; N] as $data_trait>::elt(data, i.max(0) as usize)
1521 }
1522
1523 const HAS_GET_REGION: bool = true;
1524
1525 fn get_region(
1526 x: crate::ffi::SEXP,
1527 start: crate::ffi::R_xlen_t,
1528 len: crate::ffi::R_xlen_t,
1529 buf: &mut [$elem],
1530 ) -> crate::ffi::R_xlen_t {
1531 if start < 0 || len <= 0 {
1532 return 0;
1533 }
1534 let data = unsafe {
1535 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1536 };
1537 <[$elem; N] as $data_trait>::get_region(data, start as usize, len as usize, buf)
1538 as crate::ffi::R_xlen_t
1539 }
1540
1541 $($($extra)*)?
1542 }
1543
1544 impl<const N: usize> crate::altrep_data::InferBase for [$elem; N] {
1545 const BASE: crate::altrep::RBase = $rbase;
1546
1547 unsafe fn make_class(
1548 class_name: *const i8,
1549 pkg_name: *const i8,
1550 ) -> crate::ffi::altrep::R_altrep_class_t {
1551 let cls = unsafe { $make_class_fn(class_name, pkg_name, crate::altrep_dll_info()) };
1552 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
1553 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
1554 }
1555
1556 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
1557 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
1558 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
1559 unsafe { crate::altrep_bridge::$install_family_fn::<Self>(cls) };
1560 }
1561 }
1562 };
1563}
1564
1565macro_rules! altrep_array_no_na {
1567 ($elem:ty, $data_trait:path) => {
1568 const HAS_NO_NA: bool = true;
1569
1570 fn no_na(x: crate::ffi::SEXP) -> i32 {
1571 let data =
1572 unsafe { <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1573 <[$elem; N] as $data_trait>::no_na(data)
1574 .map(i32::from)
1575 .unwrap_or(0)
1576 }
1577 };
1578}
1579
1580impl_altrep_array_numeric!(
1581 elem = i32,
1582 data_trait = crate::altrep_data::AltIntegerData,
1583 alt_trait = crate::altrep_traits::AltInteger,
1584 rbase = crate::altrep::RBase::Int,
1585 make_class_fn = crate::ffi::altrep::R_make_altinteger_class,
1586 install_family_fn = install_int,
1587 extra { altrep_array_no_na!(i32, crate::altrep_data::AltIntegerData); },
1588);
1589impl_altrep_array_numeric!(
1590 elem = f64,
1591 data_trait = crate::altrep_data::AltRealData,
1592 alt_trait = crate::altrep_traits::AltReal,
1593 rbase = crate::altrep::RBase::Real,
1594 make_class_fn = crate::ffi::altrep::R_make_altreal_class,
1595 install_family_fn = install_real,
1596 extra { altrep_array_no_na!(f64, crate::altrep_data::AltRealData); },
1597);
1598impl_altrep_array_numeric!(
1599 elem = u8,
1600 data_trait = crate::altrep_data::AltRawData,
1601 alt_trait = crate::altrep_traits::AltRaw,
1602 rbase = crate::altrep::RBase::Raw,
1603 make_class_fn = crate::ffi::altrep::R_make_altraw_class,
1604 install_family_fn = install_raw,
1605);
1606impl_altrep_array_numeric!(
1607 elem = crate::ffi::Rcomplex,
1608 data_trait = crate::altrep_data::AltComplexData,
1609 alt_trait = crate::altrep_traits::AltComplex,
1610 rbase = crate::altrep::RBase::Complex,
1611 make_class_fn = crate::ffi::altrep::R_make_altcomplex_class,
1612 install_family_fn = install_cplx,
1613);
1614
1615impl<const N: usize> crate::altrep_traits::Altrep for [bool; N] {
1617 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1618 let data =
1619 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1620 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1621 }
1622}
1623
1624impl<const N: usize> crate::altrep_traits::AltVec for [bool; N] {}
1625
1626impl<const N: usize> crate::altrep_traits::AltLogical for [bool; N] {
1627 const HAS_ELT: bool = true;
1628
1629 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
1630 let data =
1631 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1632 <[bool; N] as crate::altrep_data::AltLogicalData>::elt(data, i.max(0) as usize).to_r_int()
1633 }
1634
1635 const HAS_NO_NA: bool = true;
1636
1637 fn no_na(x: crate::ffi::SEXP) -> i32 {
1638 let data =
1639 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1640 <[bool; N] as crate::altrep_data::AltLogicalData>::no_na(data)
1641 .map(i32::from)
1642 .unwrap_or(0)
1643 }
1644}
1645
1646impl<const N: usize> crate::altrep_data::InferBase for [bool; N] {
1647 const BASE: crate::altrep::RBase = crate::altrep::RBase::Logical;
1648
1649 unsafe fn make_class(
1650 class_name: *const i8,
1651 pkg_name: *const i8,
1652 ) -> crate::ffi::altrep::R_altrep_class_t {
1653 let cls = unsafe {
1654 crate::ffi::altrep::R_make_altlogical_class(
1655 class_name,
1656 pkg_name,
1657 crate::altrep_dll_info(),
1658 )
1659 };
1660 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
1661 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
1662 }
1663
1664 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
1665 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
1666 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
1667 unsafe { crate::altrep_bridge::install_lgl::<Self>(cls) };
1668 }
1669}
1670
1671impl<const N: usize> crate::altrep_traits::Altrep for [String; N] {
1673 const GUARD: crate::altrep_traits::AltrepGuard = crate::altrep_traits::AltrepGuard::RUnwind;
1674
1675 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1676 let data =
1677 unsafe { <[String; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1678 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1679 }
1680}
1681
1682impl<const N: usize> crate::altrep_traits::AltVec for [String; N] {}
1683
1684impl<const N: usize> crate::altrep_traits::AltString for [String; N] {
1685 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::SEXP {
1686 let data =
1687 unsafe { <[String; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1688 match <[String; N] as crate::altrep_data::AltStringData>::elt(data, i.max(0) as usize) {
1689 Some(s) => unsafe { checked_mkchar(s) },
1690 None => crate::ffi::SEXP::na_string(),
1691 }
1692 }
1693}
1694
1695impl<const N: usize> crate::altrep_data::InferBase for [String; N] {
1696 const BASE: crate::altrep::RBase = crate::altrep::RBase::String;
1697
1698 unsafe fn make_class(
1699 class_name: *const i8,
1700 pkg_name: *const i8,
1701 ) -> crate::ffi::altrep::R_altrep_class_t {
1702 let cls = unsafe {
1703 crate::ffi::altrep::R_make_altstring_class(
1704 class_name,
1705 pkg_name,
1706 crate::altrep_dll_info(),
1707 )
1708 };
1709 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
1710 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
1711 }
1712
1713 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
1714 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
1715 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
1716 unsafe { crate::altrep_bridge::install_str::<Self>(cls) };
1717 }
1718}
1719impl crate::altrep_traits::Altrep for &'static [i32] {
1733 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1734 let data =
1735 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1736 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1737 }
1738}
1739
1740impl crate::altrep_traits::AltVec for &'static [i32] {
1741 const HAS_DATAPTR: bool = true;
1742
1743 fn dataptr(x: crate::ffi::SEXP, writable: bool) -> *mut std::ffi::c_void {
1744 assert!(
1746 !writable,
1747 "cannot get writable DATAPTR for static ALTREP data"
1748 );
1749 let data =
1750 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1751 data.as_ptr().cast::<std::ffi::c_void>().cast_mut()
1752 }
1753
1754 const HAS_DATAPTR_OR_NULL: bool = true;
1755
1756 fn dataptr_or_null(x: crate::ffi::SEXP) -> *const std::ffi::c_void {
1757 let data =
1758 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1759 data.as_ptr().cast::<std::ffi::c_void>()
1760 }
1761}
1762
1763impl crate::altrep_traits::AltInteger for &'static [i32] {
1764 const HAS_ELT: bool = true;
1765
1766 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
1767 let data =
1768 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1769 crate::altrep_data::AltIntegerData::elt(data, i.max(0) as usize)
1770 }
1771
1772 const HAS_GET_REGION: bool = true;
1773
1774 fn get_region(
1775 x: crate::ffi::SEXP,
1776 start: crate::ffi::R_xlen_t,
1777 len: crate::ffi::R_xlen_t,
1778 buf: &mut [i32],
1779 ) -> crate::ffi::R_xlen_t {
1780 if start < 0 || len <= 0 {
1781 return 0;
1782 }
1783 let data =
1784 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1785 let len = len as usize;
1786 crate::altrep_data::AltIntegerData::get_region(data, start as usize, len, buf)
1787 as crate::ffi::R_xlen_t
1788 }
1789
1790 const HAS_NO_NA: bool = true;
1791
1792 fn no_na(x: crate::ffi::SEXP) -> i32 {
1793 let data =
1794 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1795 crate::altrep_data::AltIntegerData::no_na(data)
1796 .map(|b| if b { 1 } else { 0 })
1797 .unwrap_or(0)
1798 }
1799
1800 const HAS_SUM: bool = true;
1801
1802 fn sum(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
1804 let data =
1805 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1806 crate::altrep_data::AltIntegerData::sum(data, narm)
1807 .map(|s| {
1808 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
1809 crate::ffi::SEXP::scalar_integer(s as i32)
1810 } else {
1811 crate::ffi::SEXP::scalar_real(s as f64)
1812 }
1813 })
1814 .unwrap_or(crate::ffi::SEXP::null())
1815 }
1816
1817 const HAS_MIN: bool = true;
1818
1819 fn min(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
1820 let data =
1821 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1822 crate::altrep_data::AltIntegerData::min(data, narm)
1823 .map(crate::ffi::SEXP::scalar_integer)
1824 .unwrap_or(crate::ffi::SEXP::null())
1825 }
1826
1827 const HAS_MAX: bool = true;
1828
1829 fn max(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
1830 let data =
1831 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1832 crate::altrep_data::AltIntegerData::max(data, narm)
1833 .map(crate::ffi::SEXP::scalar_integer)
1834 .unwrap_or(crate::ffi::SEXP::null())
1835 }
1836}
1837
1838crate::impl_inferbase_integer!(&'static [i32]);
1839
1840impl crate::altrep_traits::Altrep for &'static [f64] {
1842 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1843 let data =
1844 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1845 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1846 }
1847}
1848
1849impl crate::altrep_traits::AltVec for &'static [f64] {
1850 const HAS_DATAPTR: bool = true;
1851
1852 fn dataptr(x: crate::ffi::SEXP, writable: bool) -> *mut std::ffi::c_void {
1853 assert!(
1854 !writable,
1855 "cannot get writable DATAPTR for static ALTREP data"
1856 );
1857 let data =
1858 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1859 data.as_ptr().cast::<std::ffi::c_void>().cast_mut()
1860 }
1861
1862 const HAS_DATAPTR_OR_NULL: bool = true;
1863
1864 fn dataptr_or_null(x: crate::ffi::SEXP) -> *const std::ffi::c_void {
1865 let data =
1866 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1867 data.as_ptr().cast::<std::ffi::c_void>()
1868 }
1869}
1870
1871impl crate::altrep_traits::AltReal for &'static [f64] {
1872 const HAS_ELT: bool = true;
1873
1874 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> f64 {
1875 let data =
1876 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1877 crate::altrep_data::AltRealData::elt(data, i.max(0) as usize)
1878 }
1879
1880 const HAS_GET_REGION: bool = true;
1881
1882 fn get_region(
1883 x: crate::ffi::SEXP,
1884 start: crate::ffi::R_xlen_t,
1885 len: crate::ffi::R_xlen_t,
1886 buf: &mut [f64],
1887 ) -> crate::ffi::R_xlen_t {
1888 if start < 0 || len <= 0 {
1889 return 0;
1890 }
1891 let data =
1892 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1893 let len = len as usize;
1894 crate::altrep_data::AltRealData::get_region(data, start as usize, len, buf)
1895 as crate::ffi::R_xlen_t
1896 }
1897
1898 const HAS_NO_NA: bool = true;
1899
1900 fn no_na(x: crate::ffi::SEXP) -> i32 {
1901 let data =
1902 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1903 crate::altrep_data::AltRealData::no_na(data)
1904 .map(|b| if b { 1 } else { 0 })
1905 .unwrap_or(0)
1906 }
1907
1908 const HAS_SUM: bool = true;
1909
1910 fn sum(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
1912 let data =
1913 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1914 crate::altrep_data::AltRealData::sum(data, narm)
1915 .map(crate::ffi::SEXP::scalar_real)
1916 .unwrap_or(crate::ffi::SEXP::null())
1917 }
1918
1919 const HAS_MIN: bool = true;
1920
1921 fn min(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
1922 let data =
1923 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1924 crate::altrep_data::AltRealData::min(data, narm)
1925 .map(crate::ffi::SEXP::scalar_real)
1926 .unwrap_or(crate::ffi::SEXP::null())
1927 }
1928
1929 const HAS_MAX: bool = true;
1930
1931 fn max(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
1932 let data =
1933 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1934 crate::altrep_data::AltRealData::max(data, narm)
1935 .map(crate::ffi::SEXP::scalar_real)
1936 .unwrap_or(crate::ffi::SEXP::null())
1937 }
1938}
1939
1940crate::impl_inferbase_real!(&'static [f64]);
1941
1942impl crate::altrep_traits::Altrep for &'static [bool] {
1944 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1945 let data = unsafe {
1946 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1947 };
1948 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1949 }
1950}
1951
1952impl crate::altrep_traits::AltVec for &'static [bool] {}
1953
1954impl crate::altrep_traits::AltLogical for &'static [bool] {
1955 const HAS_ELT: bool = true;
1956
1957 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
1958 let data = unsafe {
1959 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1960 };
1961 crate::altrep_data::AltLogicalData::elt(data, i.max(0) as usize).to_r_int()
1962 }
1963
1964 const HAS_NO_NA: bool = true;
1965
1966 fn no_na(x: crate::ffi::SEXP) -> i32 {
1967 let data = unsafe {
1968 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1969 };
1970 crate::altrep_data::AltLogicalData::no_na(data)
1971 .map(|b| if b { 1 } else { 0 })
1972 .unwrap_or(0)
1973 }
1974
1975 const HAS_SUM: bool = true;
1976
1977 fn sum(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
1979 let data = unsafe {
1980 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1981 };
1982 crate::altrep_data::AltLogicalData::sum(data, narm)
1983 .map(|s| {
1984 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
1985 crate::ffi::SEXP::scalar_integer(s as i32)
1986 } else {
1987 crate::ffi::SEXP::scalar_real(s as f64)
1988 }
1989 })
1990 .unwrap_or(crate::ffi::SEXP::null())
1991 }
1992}
1993
1994crate::impl_inferbase_logical!(&'static [bool]);
1995
1996impl crate::altrep_traits::Altrep for &'static [u8] {
1998 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1999 let data =
2000 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2001 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2002 }
2003}
2004
2005impl crate::altrep_traits::AltVec for &'static [u8] {
2006 const HAS_DATAPTR: bool = true;
2007
2008 fn dataptr(x: crate::ffi::SEXP, writable: bool) -> *mut std::ffi::c_void {
2009 assert!(
2010 !writable,
2011 "cannot get writable DATAPTR for static ALTREP data"
2012 );
2013 let data =
2014 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2015 data.as_ptr().cast::<std::ffi::c_void>().cast_mut()
2016 }
2017
2018 const HAS_DATAPTR_OR_NULL: bool = true;
2019
2020 fn dataptr_or_null(x: crate::ffi::SEXP) -> *const std::ffi::c_void {
2021 let data =
2022 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2023 data.as_ptr().cast::<std::ffi::c_void>()
2024 }
2025}
2026
2027impl crate::altrep_traits::AltRaw for &'static [u8] {
2028 const HAS_ELT: bool = true;
2029
2030 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::Rbyte {
2031 let data =
2032 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2033 crate::altrep_data::AltRawData::elt(data, i.max(0) as usize)
2034 }
2035
2036 const HAS_GET_REGION: bool = true;
2037
2038 fn get_region(
2039 x: crate::ffi::SEXP,
2040 start: crate::ffi::R_xlen_t,
2041 len: crate::ffi::R_xlen_t,
2042 buf: &mut [u8],
2043 ) -> crate::ffi::R_xlen_t {
2044 if start < 0 || len <= 0 {
2045 return 0;
2046 }
2047 let data =
2048 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2049 let len = len as usize;
2050 crate::altrep_data::AltRawData::get_region(data, start as usize, len, buf)
2051 as crate::ffi::R_xlen_t
2052 }
2053}
2054
2055crate::impl_inferbase_raw!(&'static [u8]);
2056
2057impl crate::altrep_traits::Altrep for &'static [String] {
2059 const GUARD: crate::altrep_traits::AltrepGuard = crate::altrep_traits::AltrepGuard::RUnwind;
2061
2062 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2063 let data = unsafe {
2064 <&'static [String] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2065 };
2066 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2067 }
2068}
2069
2070impl crate::altrep_traits::AltVec for &'static [String] {}
2071
2072impl crate::altrep_traits::AltString for &'static [String] {
2073 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::SEXP {
2074 let data = unsafe {
2075 <&'static [String] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2076 };
2077 match crate::altrep_data::AltStringData::elt(data, i.max(0) as usize) {
2078 Some(s) => unsafe { checked_mkchar(s) },
2079 None => crate::ffi::SEXP::na_string(),
2080 }
2081 }
2082
2083 const HAS_NO_NA: bool = true;
2084
2085 fn no_na(x: crate::ffi::SEXP) -> i32 {
2086 let data = unsafe {
2087 <&'static [String] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2088 };
2089 crate::altrep_data::AltStringData::no_na(data)
2090 .map(|b| if b { 1 } else { 0 })
2091 .unwrap_or(0)
2092 }
2093}
2094
2095crate::impl_inferbase_string!(&'static [String]);
2096
2097impl crate::altrep_traits::Altrep for &'static [&'static str] {
2099 const GUARD: crate::altrep_traits::AltrepGuard = crate::altrep_traits::AltrepGuard::RUnwind;
2101
2102 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2103 let data = unsafe {
2104 <&'static [&'static str] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2105 };
2106 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2107 }
2108}
2109
2110impl crate::altrep_traits::AltVec for &'static [&'static str] {}
2111
2112impl crate::altrep_traits::AltString for &'static [&'static str] {
2113 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::SEXP {
2114 let data = unsafe {
2115 <&'static [&'static str] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2116 };
2117 match crate::altrep_data::AltStringData::elt(data, i.max(0) as usize) {
2118 Some(s) => unsafe { checked_mkchar(s) },
2119 None => crate::ffi::SEXP::na_string(),
2120 }
2121 }
2122
2123 const HAS_NO_NA: bool = true;
2124
2125 fn no_na(x: crate::ffi::SEXP) -> i32 {
2126 let data = unsafe {
2127 <&'static [&'static str] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2128 };
2129 crate::altrep_data::AltStringData::no_na(data)
2130 .map(|b| if b { 1 } else { 0 })
2131 .unwrap_or(0)
2132 }
2133}
2134
2135crate::impl_inferbase_string!(&'static [&'static str]);
2136use crate::altrep::RegisterAltrep;
2153
2154macro_rules! impl_register_altrep_builtin {
2156 ($ty:ty, $class_name:expr) => {
2157 impl RegisterAltrep for $ty {
2158 fn get_or_init_class() -> crate::ffi::altrep::R_altrep_class_t {
2159 use std::sync::OnceLock;
2160 static CLASS: OnceLock<crate::ffi::altrep::R_altrep_class_t> = OnceLock::new();
2161 *CLASS.get_or_init(|| {
2162 const CLASS_NAME: &[u8] = concat!($class_name, "\0").as_bytes();
2164 let cls = unsafe {
2165 <$ty as crate::altrep_data::InferBase>::make_class(
2166 CLASS_NAME.as_ptr().cast::<std::ffi::c_char>(),
2167 crate::AltrepPkgName::as_ptr(),
2168 )
2169 };
2170 unsafe {
2171 <$ty as crate::altrep_data::InferBase>::install_methods(cls);
2172 }
2173 cls
2174 })
2175 }
2176 }
2177 };
2178}
2179
2180impl_register_altrep_builtin!(Vec<i32>, "Vec_i32");
2182impl_register_altrep_builtin!(Vec<f64>, "Vec_f64");
2183impl_register_altrep_builtin!(Vec<bool>, "Vec_bool");
2184impl_register_altrep_builtin!(Vec<u8>, "Vec_u8");
2185impl_register_altrep_builtin!(Vec<String>, "Vec_String");
2186impl_register_altrep_builtin!(Vec<Option<String>>, "Vec_Option_String");
2187impl_register_altrep_builtin!(Vec<crate::ffi::Rcomplex>, "Vec_Rcomplex");
2188
2189impl_register_altrep_builtin!(std::ops::Range<i32>, "Range_i32");
2191impl_register_altrep_builtin!(std::ops::Range<i64>, "Range_i64");
2192impl_register_altrep_builtin!(std::ops::Range<f64>, "Range_f64");
2193
2194impl_register_altrep_builtin!(Box<[i32]>, "Box_i32");
2196impl_register_altrep_builtin!(Box<[f64]>, "Box_f64");
2197impl_register_altrep_builtin!(Box<[bool]>, "Box_bool");
2198impl_register_altrep_builtin!(Box<[u8]>, "Box_u8");
2199impl_register_altrep_builtin!(Box<[String]>, "Box_String");
2200impl_register_altrep_builtin!(Box<[crate::ffi::Rcomplex]>, "Box_Rcomplex");
2201
2202impl_register_altrep_builtin!(std::borrow::Cow<'static, [i32]>, "Cow_i32");
2204impl_register_altrep_builtin!(std::borrow::Cow<'static, [f64]>, "Cow_f64");
2205impl_register_altrep_builtin!(std::borrow::Cow<'static, [u8]>, "Cow_u8");
2206impl_register_altrep_builtin!(
2207 std::borrow::Cow<'static, [crate::ffi::Rcomplex]>,
2208 "Cow_Rcomplex"
2209);
2210
2211impl_register_altrep_builtin!(Vec<std::borrow::Cow<'static, str>>, "Vec_Cow_str");
2213impl_register_altrep_builtin!(
2214 Vec<Option<std::borrow::Cow<'static, str>>>,
2215 "Vec_Option_Cow_str"
2216);
2217