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_raw(&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 ro = {
284 let d = unsafe {
285 <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
286 };
287 <$ty as $crate::altrep_data::AltrepDataptr<$elem>>::dataptr_or_null(d)
288 };
289 if let Some(p) = ro {
290 return p.cast_mut().cast::<core::ffi::c_void>();
291 }
292 let d = unsafe {
294 <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
295 };
296 <$ty as $crate::altrep_data::AltrepDataptr<$elem>>::dataptr(d, false)
297 .map(|p| p.cast::<core::ffi::c_void>())
298 };
299
300 if let Some(p) = direct {
301 return p;
302 }
303
304 unsafe { $crate::altrep_data::materialize_altrep_data2::<$elem>(x) }
308 }
309
310 const HAS_DATAPTR_OR_NULL: bool = true;
311
312 fn dataptr_or_null(x: $crate::ffi::SEXP) -> *const core::ffi::c_void {
313 unsafe {
315 let data2 = $crate::altrep_ext::AltrepSexpExt::altrep_data2_raw(&x);
316 if !data2.is_null()
317 && $crate::ffi::SexpExt::type_of(&data2)
318 == <$elem as $crate::ffi::RNativeType>::SEXP_TYPE
319 {
320 return $crate::ffi::DATAPTR_RO(data2);
321 }
322 }
323 let d =
324 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
325 <$ty as $crate::altrep_data::AltrepDataptr<$elem>>::dataptr_or_null(d)
326 .map(|p| p.cast::<core::ffi::c_void>())
327 .unwrap_or(core::ptr::null())
328 }
329 }
330 };
331}
332
333#[macro_export]
340#[doc(hidden)]
341macro_rules! __impl_altvec_string_dataptr {
342 ($ty:ty) => {
343 impl $crate::altrep_traits::AltVec for $ty {
344 const HAS_DATAPTR: bool = true;
345
346 fn dataptr(x: $crate::ffi::SEXP, _writable: bool) -> *mut core::ffi::c_void {
347 unsafe {
348 let n = <$ty as $crate::altrep_traits::Altrep>::length(x);
349
350 let mut data2 = $crate::altrep_ext::AltrepSexpExt::altrep_data2_raw(&x);
352 let fresh_alloc = data2.is_null()
353 || $crate::ffi::SexpExt::type_of(&data2) != $crate::ffi::SEXPTYPE::STRSXP;
354 if fresh_alloc {
355 data2 = $crate::ffi::Rf_protect($crate::ffi::Rf_allocVector(
359 $crate::ffi::SEXPTYPE::STRSXP,
360 n,
361 ));
362 for j in 0..n {
363 $crate::ffi::SexpExt::set_string_elt(
364 &data2,
365 j,
366 $crate::ffi::SEXP::na_string(),
367 );
368 }
369 $crate::altrep_ext::AltrepSexpExt::set_altrep_data2(&x, data2);
370 $crate::ffi::Rf_unprotect(1);
371 }
372
373 for i in 0..n {
377 let cached = $crate::ffi::SexpExt::string_elt(&data2, i);
378 if cached != $crate::ffi::SEXP::na_string() {
379 continue; }
381 let elt = <$ty as $crate::altrep_traits::AltString>::elt(x, i);
383 $crate::ffi::SexpExt::set_string_elt(&data2, i, elt);
384 }
385
386 $crate::ffi::DATAPTR_RO(data2).cast_mut()
387 }
388 }
389
390 const HAS_DATAPTR_OR_NULL: bool = true;
391
392 fn dataptr_or_null(x: $crate::ffi::SEXP) -> *const core::ffi::c_void {
393 let _ = x;
400 core::ptr::null()
401 }
402 }
403 };
404}
405
406#[macro_export]
412#[doc(hidden)]
413macro_rules! __impl_altvec_logical_dataptr {
414 ($ty:ty) => {
415 impl $crate::altrep_data::AltrepDataptr<$crate::ffi::RLogical> for $ty {
416 fn dataptr(&mut self, _writable: bool) -> Option<*mut $crate::ffi::RLogical> {
417 None
418 }
419 }
420 $crate::__impl_altvec_dataptr!($ty, $crate::ffi::RLogical);
421 };
422}
423
424#[macro_export]
431#[doc(hidden)]
432macro_rules! __impl_altvec_integer_dataptr {
433 ($ty:ty) => {
434 impl $crate::altrep_data::AltrepDataptr<i32> for $ty {
435 fn dataptr(&mut self, _writable: bool) -> Option<*mut i32> {
436 None
437 }
438 }
439 $crate::__impl_altvec_dataptr!($ty, i32);
440 };
441}
442
443#[macro_export]
445#[doc(hidden)]
446macro_rules! __impl_altvec_real_dataptr {
447 ($ty:ty) => {
448 impl $crate::altrep_data::AltrepDataptr<f64> for $ty {
449 fn dataptr(&mut self, _writable: bool) -> Option<*mut f64> {
450 None
451 }
452 }
453 $crate::__impl_altvec_dataptr!($ty, f64);
454 };
455}
456
457#[macro_export]
459#[doc(hidden)]
460macro_rules! __impl_altvec_raw_dataptr {
461 ($ty:ty) => {
462 impl $crate::altrep_data::AltrepDataptr<u8> for $ty {
463 fn dataptr(&mut self, _writable: bool) -> Option<*mut u8> {
464 None
465 }
466 }
467 $crate::__impl_altvec_dataptr!($ty, u8);
468 };
469}
470
471#[macro_export]
473#[doc(hidden)]
474macro_rules! __impl_altvec_complex_dataptr {
475 ($ty:ty) => {
476 impl $crate::altrep_data::AltrepDataptr<$crate::ffi::Rcomplex> for $ty {
477 fn dataptr(&mut self, _writable: bool) -> Option<*mut $crate::ffi::Rcomplex> {
478 None
479 }
480 }
481 $crate::__impl_altvec_dataptr!($ty, $crate::ffi::Rcomplex);
482 };
483}
484
485#[macro_export]
487#[doc(hidden)]
488macro_rules! __impl_altvec_extract_subset {
489 ($ty:ty) => {
490 impl $crate::altrep_traits::AltVec for $ty {
491 const HAS_EXTRACT_SUBSET: bool = true;
492
493 fn extract_subset(
494 x: $crate::ffi::SEXP,
495 indx: $crate::ffi::SEXP,
496 _call: $crate::ffi::SEXP,
497 ) -> $crate::ffi::SEXP {
498 if $crate::ffi::SexpExt::type_of(&indx) != $crate::ffi::SEXPTYPE::INTSXP {
501 return core::ptr::null_mut();
502 }
503
504 let indices = unsafe { $crate::ffi::SexpExt::as_slice::<i32>(&indx) };
506
507 let data =
508 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
509 <$ty as $crate::altrep_data::AltrepExtractSubset>::extract_subset(data, indices)
510 .unwrap_or($crate::ffi::SEXP::nil())
511 }
512 }
513 };
514}
515#[macro_export]
528#[doc(hidden)]
529macro_rules! __impl_alt_elt {
530 ($ty:ty, $trait:path, $elem:ty, $na:expr) => {
531 const HAS_ELT: bool = true;
532
533 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> $elem {
534 let data =
535 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
536 <$ty as $trait>::elt(data, i.max(0) as usize)
537 }
538 };
539}
540
541#[macro_export]
546#[doc(hidden)]
547macro_rules! __impl_alt_get_region {
548 ($ty:ty, $trait:path, $buf_ty:ty) => {
549 const HAS_GET_REGION: bool = true;
550
551 fn get_region(
552 x: $crate::ffi::SEXP,
553 start: $crate::ffi::R_xlen_t,
554 len: $crate::ffi::R_xlen_t,
555 buf: &mut [$buf_ty],
556 ) -> $crate::ffi::R_xlen_t {
557 if start < 0 || len <= 0 {
558 return 0;
559 }
560 let data =
561 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
562 let len = len as usize;
563 <$ty as $trait>::get_region(data, start as usize, len, buf) as $crate::ffi::R_xlen_t
564 }
565 };
566}
567
568#[macro_export]
573#[doc(hidden)]
574macro_rules! __impl_alt_is_sorted {
575 ($ty:ty, $trait:path) => {
576 const HAS_IS_SORTED: bool = true;
577
578 fn is_sorted(x: $crate::ffi::SEXP) -> i32 {
579 let data =
580 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
581 <$ty as $trait>::is_sorted(data)
582 .map(|s| s.to_r_int())
583 .unwrap_or(i32::MIN)
584 }
585 };
586}
587
588#[macro_export]
593#[doc(hidden)]
594macro_rules! __impl_alt_no_na {
595 ($ty:ty, $trait:path) => {
596 const HAS_NO_NA: bool = true;
597
598 fn no_na(x: $crate::ffi::SEXP) -> i32 {
599 let data =
600 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
601 <$ty as $trait>::no_na(data)
602 .map(|b| if b { 1 } else { 0 })
603 .unwrap_or(0)
604 }
605 };
606}
607#[macro_export]
617#[doc(hidden)]
618macro_rules! __impl_alt_from_data {
619 ($ty:ty, $methods:ident, $inferbase:ident) => {
621 $crate::__impl_altrep_base!($ty);
622 impl $crate::altrep_traits::AltVec for $ty {}
623 $crate::$methods!($ty);
624 $crate::$inferbase!($ty);
625 };
626 ($ty:ty, $methods:ident, $inferbase:ident, @guard $guard:ident) => {
628 $crate::__impl_altrep_base!($ty, $guard);
629 impl $crate::altrep_traits::AltVec for $ty {}
630 $crate::$methods!($ty);
631 $crate::$inferbase!($ty);
632 };
633 ($ty:ty, $methods:ident, $inferbase:ident, dataptr($elem:ty)) => {
635 $crate::__impl_altrep_base!($ty);
636 $crate::__impl_altvec_dataptr!($ty, $elem);
637 $crate::$methods!($ty);
638 $crate::$inferbase!($ty);
639 };
640 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr) => {
642 $crate::__impl_altrep_base!($ty);
643 $crate::__impl_altvec_string_dataptr!($ty);
644 $crate::$methods!($ty);
645 $crate::$inferbase!($ty);
646 };
647 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr, @guard $guard:ident) => {
649 $crate::__impl_altrep_base!($ty, $guard);
650 $crate::__impl_altvec_string_dataptr!($ty);
651 $crate::$methods!($ty);
652 $crate::$inferbase!($ty);
653 };
654 ($ty:ty, $methods:ident, $inferbase:ident, serialize) => {
656 $crate::__impl_altrep_base_with_serialize!($ty);
657 impl $crate::altrep_traits::AltVec for $ty {}
658 $crate::$methods!($ty);
659 $crate::$inferbase!($ty);
660 };
661 ($ty:ty, $methods:ident, $inferbase:ident, serialize, @guard $guard:ident) => {
663 $crate::__impl_altrep_base_with_serialize!($ty, $guard);
664 impl $crate::altrep_traits::AltVec for $ty {}
665 $crate::$methods!($ty);
666 $crate::$inferbase!($ty);
667 };
668 ($ty:ty, $methods:ident, $inferbase:ident, subset) => {
670 $crate::__impl_altrep_base!($ty);
671 $crate::__impl_altvec_extract_subset!($ty);
672 $crate::$methods!($ty);
673 $crate::$inferbase!($ty);
674 };
675 ($ty:ty, $methods:ident, $inferbase:ident, dataptr($elem:ty), serialize) => {
677 $crate::__impl_altrep_base_with_serialize!($ty);
678 $crate::__impl_altvec_dataptr!($ty, $elem);
679 $crate::$methods!($ty);
680 $crate::$inferbase!($ty);
681 };
682 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr, serialize) => {
684 $crate::__impl_altrep_base_with_serialize!($ty);
685 $crate::__impl_altvec_string_dataptr!($ty);
686 $crate::$methods!($ty);
687 $crate::$inferbase!($ty);
688 };
689 ($ty:ty, $methods:ident, $inferbase:ident, string_dataptr, serialize, @guard $guard:ident) => {
691 $crate::__impl_altrep_base_with_serialize!($ty, $guard);
692 $crate::__impl_altvec_string_dataptr!($ty);
693 $crate::$methods!($ty);
694 $crate::$inferbase!($ty);
695 };
696 ($ty:ty, $methods:ident, $inferbase:ident, subset, serialize) => {
698 $crate::__impl_altrep_base_with_serialize!($ty);
699 $crate::__impl_altvec_extract_subset!($ty);
700 $crate::$methods!($ty);
701 $crate::$inferbase!($ty);
702 };
703}
704#[macro_export]
710#[doc(hidden)]
711macro_rules! __impl_altinteger_methods {
712 ($ty:ty) => {
713 impl $crate::altrep_traits::AltInteger for $ty {
714 $crate::__impl_alt_elt!($ty, $crate::altrep_data::AltIntegerData, i32, i32::MIN);
715 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltIntegerData, i32);
716 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltIntegerData);
717 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltIntegerData);
718
719 const HAS_SUM: bool = true;
720
721 fn sum(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
723 let data =
724 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
725 match <$ty as $crate::altrep_data::AltIntegerData>::sum(data, narm) {
726 Some(s) => {
727 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
728 $crate::ffi::SEXP::scalar_integer(s as i32)
729 } else {
730 $crate::ffi::SEXP::scalar_real(s as f64)
731 }
732 }
733 None => $crate::ffi::SEXP::null(),
734 }
735 }
736
737 const HAS_MIN: bool = true;
738
739 fn min(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
740 let data =
741 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
742 <$ty as $crate::altrep_data::AltIntegerData>::min(data, narm)
743 .map(|m| $crate::ffi::SEXP::scalar_integer(m))
744 .unwrap_or($crate::ffi::SEXP::null())
745 }
746
747 const HAS_MAX: bool = true;
748
749 fn max(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
750 let data =
751 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
752 <$ty as $crate::altrep_data::AltIntegerData>::max(data, narm)
753 .map(|m| $crate::ffi::SEXP::scalar_integer(m))
754 .unwrap_or($crate::ffi::SEXP::null())
755 }
756 }
757 };
758}
759
760#[macro_export]
782macro_rules! impl_altreal_from_data {
783 ($ty:ty) => {
784 $crate::__impl_altrep_base!($ty);
785 $crate::__impl_altvec_real_dataptr!($ty);
786 $crate::__impl_altreal_methods!($ty);
787 $crate::impl_inferbase_real!($ty);
788 };
789 ($ty:ty, dataptr) => {
790 $crate::__impl_alt_from_data!(
791 $ty,
792 __impl_altreal_methods,
793 impl_inferbase_real,
794 dataptr(f64)
795 );
796 };
797 ($ty:ty, serialize) => {
798 $crate::__impl_altrep_base_with_serialize!($ty);
799 $crate::__impl_altvec_real_dataptr!($ty);
800 $crate::__impl_altreal_methods!($ty);
801 $crate::impl_inferbase_real!($ty);
802 };
803 ($ty:ty, dataptr, serialize) => {
804 $crate::__impl_alt_from_data!(
805 $ty,
806 __impl_altreal_methods,
807 impl_inferbase_real,
808 dataptr(f64),
809 serialize
810 );
811 };
812 ($ty:ty, serialize, dataptr) => {
813 $crate::impl_altreal_from_data!($ty, dataptr, serialize);
814 };
815 ($ty:ty, subset) => {
816 $crate::__impl_alt_from_data!($ty, __impl_altreal_methods, impl_inferbase_real, subset);
817 };
818 ($ty:ty, subset, serialize) => {
819 $crate::__impl_alt_from_data!(
820 $ty,
821 __impl_altreal_methods,
822 impl_inferbase_real,
823 subset,
824 serialize
825 );
826 };
827 ($ty:ty, serialize, subset) => {
828 $crate::impl_altreal_from_data!($ty, subset, serialize);
829 };
830 ($ty:ty, materializing_dataptr) => {
832 $crate::__impl_altrep_base!($ty);
833 $crate::__impl_altvec_real_dataptr!($ty);
834 $crate::__impl_altreal_methods!($ty);
835 $crate::impl_inferbase_real!($ty);
836 };
837 ($ty:ty, materializing_dataptr, serialize) => {
839 $crate::__impl_altrep_base_with_serialize!($ty);
840 $crate::__impl_altvec_real_dataptr!($ty);
841 $crate::__impl_altreal_methods!($ty);
842 $crate::impl_inferbase_real!($ty);
843 };
844}
845
846#[macro_export]
848#[doc(hidden)]
849macro_rules! __impl_altreal_methods {
850 ($ty:ty) => {
851 impl $crate::altrep_traits::AltReal for $ty {
852 $crate::__impl_alt_elt!($ty, $crate::altrep_data::AltRealData, f64, f64::NAN);
853 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltRealData, f64);
854 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltRealData);
855 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltRealData);
856
857 const HAS_SUM: bool = true;
858
859 fn sum(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
861 let data =
862 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
863 <$ty as $crate::altrep_data::AltRealData>::sum(data, narm)
864 .map(|s| $crate::ffi::SEXP::scalar_real(s))
865 .unwrap_or($crate::ffi::SEXP::null())
866 }
867
868 const HAS_MIN: bool = true;
869
870 fn min(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
871 let data =
872 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
873 <$ty as $crate::altrep_data::AltRealData>::min(data, narm)
874 .map(|m| $crate::ffi::SEXP::scalar_real(m))
875 .unwrap_or($crate::ffi::SEXP::null())
876 }
877
878 const HAS_MAX: bool = true;
879
880 fn max(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
881 let data =
882 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
883 <$ty as $crate::altrep_data::AltRealData>::max(data, narm)
884 .map(|m| $crate::ffi::SEXP::scalar_real(m))
885 .unwrap_or($crate::ffi::SEXP::null())
886 }
887 }
888 };
889}
890
891#[macro_export]
913macro_rules! impl_altlogical_from_data {
914 ($ty:ty) => {
915 $crate::__impl_altrep_base!($ty);
916 $crate::__impl_altvec_logical_dataptr!($ty);
917 $crate::__impl_altlogical_methods!($ty);
918 $crate::impl_inferbase_logical!($ty);
919 };
920 ($ty:ty, dataptr) => {
921 $crate::__impl_alt_from_data!(
922 $ty,
923 __impl_altlogical_methods,
924 impl_inferbase_logical,
925 dataptr(i32)
926 );
927 };
928 ($ty:ty, serialize) => {
929 $crate::__impl_altrep_base_with_serialize!($ty);
930 $crate::__impl_altvec_logical_dataptr!($ty);
931 $crate::__impl_altlogical_methods!($ty);
932 $crate::impl_inferbase_logical!($ty);
933 };
934 ($ty:ty, dataptr, serialize) => {
935 $crate::__impl_alt_from_data!(
936 $ty,
937 __impl_altlogical_methods,
938 impl_inferbase_logical,
939 dataptr(i32),
940 serialize
941 );
942 };
943 ($ty:ty, serialize, dataptr) => {
944 $crate::impl_altlogical_from_data!($ty, dataptr, serialize);
945 };
946 ($ty:ty, subset) => {
947 $crate::__impl_alt_from_data!(
948 $ty,
949 __impl_altlogical_methods,
950 impl_inferbase_logical,
951 subset
952 );
953 };
954 ($ty:ty, subset, serialize) => {
955 $crate::__impl_alt_from_data!(
956 $ty,
957 __impl_altlogical_methods,
958 impl_inferbase_logical,
959 subset,
960 serialize
961 );
962 };
963 ($ty:ty, serialize, subset) => {
964 $crate::impl_altlogical_from_data!($ty, subset, serialize);
965 };
966 ($ty:ty, materializing_dataptr) => {
968 $crate::__impl_altrep_base!($ty);
969 $crate::__impl_altvec_logical_dataptr!($ty);
970 $crate::__impl_altlogical_methods!($ty);
971 $crate::impl_inferbase_logical!($ty);
972 };
973 ($ty:ty, materializing_dataptr, serialize) => {
975 $crate::__impl_altrep_base_with_serialize!($ty);
976 $crate::__impl_altvec_logical_dataptr!($ty);
977 $crate::__impl_altlogical_methods!($ty);
978 $crate::impl_inferbase_logical!($ty);
979 };
980}
981
982#[macro_export]
984#[doc(hidden)]
985macro_rules! __impl_altlogical_methods {
986 ($ty:ty) => {
987 impl $crate::altrep_traits::AltLogical for $ty {
988 const HAS_ELT: bool = true;
990
991 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> i32 {
992 let data =
993 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
994 <$ty as $crate::altrep_data::AltLogicalData>::elt(data, i.max(0) as usize)
995 .to_r_int()
996 }
997
998 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltLogicalData, i32);
999 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltLogicalData);
1000 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltLogicalData);
1001
1002 const HAS_SUM: bool = true;
1003
1004 fn sum(x: $crate::ffi::SEXP, narm: bool) -> $crate::ffi::SEXP {
1006 let data =
1007 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1008 match <$ty as $crate::altrep_data::AltLogicalData>::sum(data, narm) {
1009 Some(s) => {
1010 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
1011 $crate::ffi::SEXP::scalar_integer(s as i32)
1012 } else {
1013 $crate::ffi::SEXP::scalar_real(s as f64)
1014 }
1015 }
1016 None => $crate::ffi::SEXP::null(),
1017 }
1018 }
1019 }
1020 };
1021}
1022
1023#[macro_export]
1045macro_rules! impl_altraw_from_data {
1046 ($ty:ty) => {
1047 $crate::__impl_altrep_base!($ty);
1048 $crate::__impl_altvec_raw_dataptr!($ty);
1049 $crate::__impl_altraw_methods!($ty);
1050 $crate::impl_inferbase_raw!($ty);
1051 };
1052 ($ty:ty, dataptr) => {
1053 $crate::__impl_alt_from_data!($ty, __impl_altraw_methods, impl_inferbase_raw, dataptr(u8));
1054 };
1055 ($ty:ty, serialize) => {
1056 $crate::__impl_altrep_base_with_serialize!($ty);
1057 $crate::__impl_altvec_raw_dataptr!($ty);
1058 $crate::__impl_altraw_methods!($ty);
1059 $crate::impl_inferbase_raw!($ty);
1060 };
1061 ($ty:ty, dataptr, serialize) => {
1062 $crate::__impl_alt_from_data!(
1063 $ty,
1064 __impl_altraw_methods,
1065 impl_inferbase_raw,
1066 dataptr(u8),
1067 serialize
1068 );
1069 };
1070 ($ty:ty, serialize, dataptr) => {
1071 $crate::impl_altraw_from_data!($ty, dataptr, serialize);
1072 };
1073 ($ty:ty, subset) => {
1074 $crate::__impl_alt_from_data!($ty, __impl_altraw_methods, impl_inferbase_raw, subset);
1075 };
1076 ($ty:ty, subset, serialize) => {
1077 $crate::__impl_alt_from_data!(
1078 $ty,
1079 __impl_altraw_methods,
1080 impl_inferbase_raw,
1081 subset,
1082 serialize
1083 );
1084 };
1085 ($ty:ty, serialize, subset) => {
1086 $crate::impl_altraw_from_data!($ty, subset, serialize);
1087 };
1088}
1089
1090#[macro_export]
1092#[doc(hidden)]
1093macro_rules! __impl_altraw_methods {
1094 ($ty:ty) => {
1095 impl $crate::altrep_traits::AltRaw for $ty {
1096 $crate::__impl_alt_elt!($ty, $crate::altrep_data::AltRawData, u8, 0);
1097 $crate::__impl_alt_get_region!($ty, $crate::altrep_data::AltRawData, u8);
1098 }
1099 };
1100}
1101
1102#[macro_export]
1124macro_rules! impl_altstring_from_data {
1125 ($ty:ty) => {
1126 $crate::__impl_altrep_base!($ty);
1127 $crate::__impl_altvec_string_dataptr!($ty);
1128 $crate::__impl_altstring_methods!($ty);
1129 $crate::impl_inferbase_string!($ty);
1130 };
1131 ($ty:ty, dataptr) => {
1132 $crate::__impl_alt_from_data!(
1133 $ty,
1134 __impl_altstring_methods,
1135 impl_inferbase_string,
1136 string_dataptr
1137 );
1138 };
1139 ($ty:ty, serialize) => {
1140 $crate::__impl_altrep_base_with_serialize!($ty);
1141 $crate::__impl_altvec_string_dataptr!($ty);
1142 $crate::__impl_altstring_methods!($ty);
1143 $crate::impl_inferbase_string!($ty);
1144 };
1145 ($ty:ty, dataptr, serialize) => {
1146 $crate::__impl_alt_from_data!(
1147 $ty,
1148 __impl_altstring_methods,
1149 impl_inferbase_string,
1150 string_dataptr,
1151 serialize
1152 );
1153 };
1154 ($ty:ty, subset) => {
1155 $crate::__impl_alt_from_data!($ty, __impl_altstring_methods, impl_inferbase_string, subset);
1156 };
1157 ($ty:ty, subset, serialize) => {
1158 $crate::__impl_alt_from_data!(
1159 $ty,
1160 __impl_altstring_methods,
1161 impl_inferbase_string,
1162 subset,
1163 serialize
1164 );
1165 };
1166 ($ty:ty, serialize, subset) => {
1167 $crate::impl_altstring_from_data!($ty, subset, serialize);
1168 };
1169}
1170
1171#[macro_export]
1173#[doc(hidden)]
1174macro_rules! __impl_altstring_methods {
1175 ($ty:ty) => {
1176 impl $crate::altrep_traits::AltString for $ty {
1177 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> $crate::ffi::SEXP {
1187 unsafe {
1188 let idx = i.max(0) as usize;
1189
1190 let mut data2 = $crate::altrep_ext::AltrepSexpExt::altrep_data2_raw(&x);
1192 if data2.is_null()
1193 || $crate::ffi::SexpExt::type_of(&data2) != $crate::ffi::SEXPTYPE::STRSXP
1194 {
1195 let n = <$ty as $crate::altrep_traits::Altrep>::length(x);
1196 data2 = $crate::ffi::Rf_protect($crate::ffi::Rf_allocVector(
1199 $crate::ffi::SEXPTYPE::STRSXP,
1200 n,
1201 ));
1202 for j in 0..n {
1203 $crate::ffi::SexpExt::set_string_elt(
1204 &data2,
1205 j,
1206 $crate::ffi::SEXP::na_string(),
1207 );
1208 }
1209 $crate::altrep_ext::AltrepSexpExt::set_altrep_data2(&x, data2);
1210 $crate::ffi::Rf_unprotect(1);
1211 }
1212
1213 let cached = $crate::ffi::SexpExt::string_elt(&data2, i);
1215 if cached != $crate::ffi::SEXP::na_string() {
1216 return cached;
1217 }
1218
1219 let data = <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x);
1221 match <$ty as $crate::altrep_data::AltStringData>::elt(data, idx) {
1222 Some(s) => {
1223 let charsxp = $crate::altrep_impl::checked_mkchar(s);
1224 $crate::ffi::SexpExt::set_string_elt(&data2, i, charsxp);
1225 charsxp
1226 }
1227 None => $crate::ffi::SEXP::na_string(),
1228 }
1229 }
1230 }
1231
1232 $crate::__impl_alt_is_sorted!($ty, $crate::altrep_data::AltStringData);
1233 $crate::__impl_alt_no_na!($ty, $crate::altrep_data::AltStringData);
1234 }
1235 };
1236}
1237
1238#[macro_export]
1240macro_rules! impl_altlist_from_data {
1241 ($ty:ty) => {
1242 $crate::impl_altlist_from_data!($ty, RUnwind);
1243 };
1244 ($ty:ty, $guard:ident) => {
1245 impl $crate::altrep_traits::Altrep for $ty {
1246 const GUARD: $crate::altrep_traits::AltrepGuard =
1247 $crate::altrep_traits::AltrepGuard::$guard;
1248
1249 fn length(x: $crate::ffi::SEXP) -> $crate::ffi::R_xlen_t {
1250 let data =
1251 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1252 <$ty as $crate::altrep_data::AltrepLen>::len(data) as $crate::ffi::R_xlen_t
1253 }
1254 }
1255
1256 impl $crate::altrep_traits::AltVec for $ty {}
1257
1258 impl $crate::altrep_traits::AltList for $ty {
1259 fn elt(x: $crate::ffi::SEXP, i: $crate::ffi::R_xlen_t) -> $crate::ffi::SEXP {
1260 let data =
1261 unsafe { <$ty as $crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1262 <$ty as $crate::altrep_data::AltListData>::elt(data, i.max(0) as usize)
1263 }
1264 }
1265
1266 $crate::impl_inferbase_list!($ty);
1267 };
1268}
1269
1270#[macro_export]
1272#[doc(hidden)]
1273macro_rules! __impl_altcomplex_methods {
1274 ($ty:ty) => {
1275 impl $crate::altrep_traits::AltComplex for $ty {
1276 $crate::__impl_alt_elt!(
1277 $ty,
1278 $crate::altrep_data::AltComplexData,
1279 $crate::ffi::Rcomplex,
1280 $crate::ffi::Rcomplex {
1281 r: f64::NAN,
1282 i: f64::NAN
1283 }
1284 );
1285 $crate::__impl_alt_get_region!(
1286 $ty,
1287 $crate::altrep_data::AltComplexData,
1288 $crate::ffi::Rcomplex
1289 );
1290 }
1291 };
1292}
1293
1294#[macro_export]
1301macro_rules! impl_altcomplex_from_data {
1302 ($ty:ty) => {
1303 $crate::__impl_altrep_base!($ty);
1304 $crate::__impl_altvec_complex_dataptr!($ty);
1305 $crate::__impl_altcomplex_methods!($ty);
1306 $crate::impl_inferbase_complex!($ty);
1307 };
1308 ($ty:ty, dataptr) => {
1309 $crate::__impl_alt_from_data!(
1310 $ty,
1311 __impl_altcomplex_methods,
1312 impl_inferbase_complex,
1313 dataptr($crate::ffi::Rcomplex)
1314 );
1315 };
1316 ($ty:ty, serialize) => {
1317 $crate::__impl_altrep_base_with_serialize!($ty);
1318 $crate::__impl_altvec_complex_dataptr!($ty);
1319 $crate::__impl_altcomplex_methods!($ty);
1320 $crate::impl_inferbase_complex!($ty);
1321 };
1322 ($ty:ty, subset) => {
1323 $crate::__impl_alt_from_data!(
1324 $ty,
1325 __impl_altcomplex_methods,
1326 impl_inferbase_complex,
1327 subset
1328 );
1329 };
1330 ($ty:ty, dataptr, serialize) => {
1331 $crate::__impl_alt_from_data!(
1332 $ty,
1333 __impl_altcomplex_methods,
1334 impl_inferbase_complex,
1335 dataptr($crate::ffi::Rcomplex),
1336 serialize
1337 );
1338 };
1339 ($ty:ty, serialize, dataptr) => {
1340 $crate::impl_altcomplex_from_data!($ty, dataptr, serialize);
1341 };
1342 ($ty:ty, subset, serialize) => {
1343 $crate::__impl_alt_from_data!(
1344 $ty,
1345 __impl_altcomplex_methods,
1346 impl_inferbase_complex,
1347 subset,
1348 serialize
1349 );
1350 };
1351 ($ty:ty, serialize, subset) => {
1352 $crate::impl_altcomplex_from_data!($ty, subset, serialize);
1353 };
1354}
1355#[doc(hidden)]
1418macro_rules! impl_builtin_altrep_family {
1419 ($ty:ty, integer, dataptr, $reg_fn:ident, $entry_ident:ident) => {
1421 $crate::impl_altinteger_from_data!($ty, dataptr, serialize);
1422 #[doc(hidden)]
1423 #[unsafe(no_mangle)]
1424 pub extern "C" fn $reg_fn() {
1425 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1426 }
1427 #[cfg_attr(
1428 not(target_arch = "wasm32"),
1429 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1430 linkme(crate = $crate::linkme)
1431 )]
1432 #[doc(hidden)]
1433 #[allow(non_upper_case_globals)]
1434 static $entry_ident: $crate::registry::AltrepRegistration =
1435 $crate::registry::AltrepRegistration {
1436 register: $reg_fn,
1437 symbol: stringify!($reg_fn),
1438 };
1439 };
1440 ($ty:ty, real, dataptr, $reg_fn:ident, $entry_ident:ident) => {
1441 $crate::impl_altreal_from_data!($ty, dataptr, serialize);
1442 #[doc(hidden)]
1443 #[unsafe(no_mangle)]
1444 pub extern "C" fn $reg_fn() {
1445 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1446 }
1447 #[cfg_attr(
1448 not(target_arch = "wasm32"),
1449 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1450 linkme(crate = $crate::linkme)
1451 )]
1452 #[doc(hidden)]
1453 #[allow(non_upper_case_globals)]
1454 static $entry_ident: $crate::registry::AltrepRegistration =
1455 $crate::registry::AltrepRegistration {
1456 register: $reg_fn,
1457 symbol: stringify!($reg_fn),
1458 };
1459 };
1460 ($ty:ty, logical, dataptr, $reg_fn:ident, $entry_ident:ident) => {
1461 $crate::impl_altlogical_from_data!($ty, dataptr, serialize);
1462 #[doc(hidden)]
1463 #[unsafe(no_mangle)]
1464 pub extern "C" fn $reg_fn() {
1465 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1466 }
1467 #[cfg_attr(
1468 not(target_arch = "wasm32"),
1469 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1470 linkme(crate = $crate::linkme)
1471 )]
1472 #[doc(hidden)]
1473 #[allow(non_upper_case_globals)]
1474 static $entry_ident: $crate::registry::AltrepRegistration =
1475 $crate::registry::AltrepRegistration {
1476 register: $reg_fn,
1477 symbol: stringify!($reg_fn),
1478 };
1479 };
1480 ($ty:ty, raw, dataptr, $reg_fn:ident, $entry_ident:ident) => {
1481 $crate::impl_altraw_from_data!($ty, dataptr, serialize);
1482 #[doc(hidden)]
1483 #[unsafe(no_mangle)]
1484 pub extern "C" fn $reg_fn() {
1485 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1486 }
1487 #[cfg_attr(
1488 not(target_arch = "wasm32"),
1489 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1490 linkme(crate = $crate::linkme)
1491 )]
1492 #[doc(hidden)]
1493 #[allow(non_upper_case_globals)]
1494 static $entry_ident: $crate::registry::AltrepRegistration =
1495 $crate::registry::AltrepRegistration {
1496 register: $reg_fn,
1497 symbol: stringify!($reg_fn),
1498 };
1499 };
1500 ($ty:ty, string, dataptr, $reg_fn:ident, $entry_ident:ident) => {
1501 $crate::impl_altstring_from_data!($ty, dataptr, serialize);
1502 #[doc(hidden)]
1503 #[unsafe(no_mangle)]
1504 pub extern "C" fn $reg_fn() {
1505 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1506 }
1507 #[cfg_attr(
1508 not(target_arch = "wasm32"),
1509 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1510 linkme(crate = $crate::linkme)
1511 )]
1512 #[doc(hidden)]
1513 #[allow(non_upper_case_globals)]
1514 static $entry_ident: $crate::registry::AltrepRegistration =
1515 $crate::registry::AltrepRegistration {
1516 register: $reg_fn,
1517 symbol: stringify!($reg_fn),
1518 };
1519 };
1520 ($ty:ty, complex, dataptr, $reg_fn:ident, $entry_ident:ident) => {
1521 $crate::impl_altcomplex_from_data!($ty, dataptr, serialize);
1522 #[doc(hidden)]
1523 #[unsafe(no_mangle)]
1524 pub extern "C" fn $reg_fn() {
1525 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1526 }
1527 #[cfg_attr(
1528 not(target_arch = "wasm32"),
1529 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1530 linkme(crate = $crate::linkme)
1531 )]
1532 #[doc(hidden)]
1533 #[allow(non_upper_case_globals)]
1534 static $entry_ident: $crate::registry::AltrepRegistration =
1535 $crate::registry::AltrepRegistration {
1536 register: $reg_fn,
1537 symbol: stringify!($reg_fn),
1538 };
1539 };
1540 ($ty:ty, integer, materializing, $reg_fn:ident, $entry_ident:ident) => {
1544 $crate::impl_altinteger_from_data!($ty, materializing_dataptr, serialize);
1545 #[doc(hidden)]
1546 #[unsafe(no_mangle)]
1547 pub extern "C" fn $reg_fn() {
1548 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1549 }
1550 #[cfg_attr(
1551 not(target_arch = "wasm32"),
1552 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1553 linkme(crate = $crate::linkme)
1554 )]
1555 #[doc(hidden)]
1556 #[allow(non_upper_case_globals)]
1557 static $entry_ident: $crate::registry::AltrepRegistration =
1558 $crate::registry::AltrepRegistration {
1559 register: $reg_fn,
1560 symbol: stringify!($reg_fn),
1561 };
1562 };
1563 ($ty:ty, real, materializing, $reg_fn:ident, $entry_ident:ident) => {
1564 $crate::impl_altreal_from_data!($ty, materializing_dataptr, serialize);
1565 #[doc(hidden)]
1566 #[unsafe(no_mangle)]
1567 pub extern "C" fn $reg_fn() {
1568 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1569 }
1570 #[cfg_attr(
1571 not(target_arch = "wasm32"),
1572 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1573 linkme(crate = $crate::linkme)
1574 )]
1575 #[doc(hidden)]
1576 #[allow(non_upper_case_globals)]
1577 static $entry_ident: $crate::registry::AltrepRegistration =
1578 $crate::registry::AltrepRegistration {
1579 register: $reg_fn,
1580 symbol: stringify!($reg_fn),
1581 };
1582 };
1583 ($ty:ty, logical, materializing, $reg_fn:ident, $entry_ident:ident) => {
1584 $crate::impl_altlogical_from_data!($ty, materializing_dataptr, serialize);
1585 #[doc(hidden)]
1586 #[unsafe(no_mangle)]
1587 pub extern "C" fn $reg_fn() {
1588 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1589 }
1590 #[cfg_attr(
1591 not(target_arch = "wasm32"),
1592 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1593 linkme(crate = $crate::linkme)
1594 )]
1595 #[doc(hidden)]
1596 #[allow(non_upper_case_globals)]
1597 static $entry_ident: $crate::registry::AltrepRegistration =
1598 $crate::registry::AltrepRegistration {
1599 register: $reg_fn,
1600 symbol: stringify!($reg_fn),
1601 };
1602 };
1603 ($ty:ty, raw, materializing, $reg_fn:ident, $entry_ident:ident) => {
1604 $crate::impl_altraw_from_data!($ty, materializing_dataptr, serialize);
1605 #[doc(hidden)]
1606 #[unsafe(no_mangle)]
1607 pub extern "C" fn $reg_fn() {
1608 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1609 }
1610 #[cfg_attr(
1611 not(target_arch = "wasm32"),
1612 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1613 linkme(crate = $crate::linkme)
1614 )]
1615 #[doc(hidden)]
1616 #[allow(non_upper_case_globals)]
1617 static $entry_ident: $crate::registry::AltrepRegistration =
1618 $crate::registry::AltrepRegistration {
1619 register: $reg_fn,
1620 symbol: stringify!($reg_fn),
1621 };
1622 };
1623 ($ty:ty, string, materializing, $reg_fn:ident, $entry_ident:ident) => {
1624 $crate::impl_altstring_from_data!($ty, materializing_dataptr, serialize);
1625 #[doc(hidden)]
1626 #[unsafe(no_mangle)]
1627 pub extern "C" fn $reg_fn() {
1628 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1629 }
1630 #[cfg_attr(
1631 not(target_arch = "wasm32"),
1632 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1633 linkme(crate = $crate::linkme)
1634 )]
1635 #[doc(hidden)]
1636 #[allow(non_upper_case_globals)]
1637 static $entry_ident: $crate::registry::AltrepRegistration =
1638 $crate::registry::AltrepRegistration {
1639 register: $reg_fn,
1640 symbol: stringify!($reg_fn),
1641 };
1642 };
1643 ($ty:ty, complex, materializing, $reg_fn:ident, $entry_ident:ident) => {
1644 $crate::impl_altcomplex_from_data!($ty, materializing_dataptr, serialize);
1645 #[doc(hidden)]
1646 #[unsafe(no_mangle)]
1647 pub extern "C" fn $reg_fn() {
1648 <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
1649 }
1650 #[cfg_attr(
1651 not(target_arch = "wasm32"),
1652 $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
1653 linkme(crate = $crate::linkme)
1654 )]
1655 #[doc(hidden)]
1656 #[allow(non_upper_case_globals)]
1657 static $entry_ident: $crate::registry::AltrepRegistration =
1658 $crate::registry::AltrepRegistration {
1659 register: $reg_fn,
1660 symbol: stringify!($reg_fn),
1661 };
1662 };
1663}
1664
1665impl_builtin_altrep_family!(
1675 Vec<i32>,
1676 integer,
1677 dataptr,
1678 __mx_altrep_reg_builtin_Vec_i32,
1679 __MX_ALTREP_REG_ENTRY_builtin_Vec_i32
1680);
1681impl_builtin_altrep_family!(
1682 Vec<f64>,
1683 real,
1684 dataptr,
1685 __mx_altrep_reg_builtin_Vec_f64,
1686 __MX_ALTREP_REG_ENTRY_builtin_Vec_f64
1687);
1688impl_builtin_altrep_family!(
1689 Vec<bool>,
1690 logical,
1691 materializing,
1692 __mx_altrep_reg_builtin_Vec_bool,
1693 __MX_ALTREP_REG_ENTRY_builtin_Vec_bool
1694);
1695impl_builtin_altrep_family!(
1696 Vec<u8>,
1697 raw,
1698 dataptr,
1699 __mx_altrep_reg_builtin_Vec_u8,
1700 __MX_ALTREP_REG_ENTRY_builtin_Vec_u8
1701);
1702impl_builtin_altrep_family!(
1703 Vec<String>,
1704 string,
1705 dataptr,
1706 __mx_altrep_reg_builtin_Vec_String,
1707 __MX_ALTREP_REG_ENTRY_builtin_Vec_String
1708);
1709impl_builtin_altrep_family!(
1710 Vec<Option<String>>,
1711 string,
1712 dataptr,
1713 __mx_altrep_reg_builtin_Vec_Option_String,
1714 __MX_ALTREP_REG_ENTRY_builtin_Vec_Option_String
1715);
1716impl_builtin_altrep_family!(
1720 Vec<std::borrow::Cow<'static, str>>,
1721 string,
1722 dataptr,
1723 __mx_altrep_reg_builtin_Vec_Cow_str,
1724 __MX_ALTREP_REG_ENTRY_builtin_Vec_Cow_str
1725);
1726impl_builtin_altrep_family!(
1727 Vec<Option<std::borrow::Cow<'static, str>>>,
1728 string,
1729 dataptr,
1730 __mx_altrep_reg_builtin_Vec_Option_Cow_str,
1731 __MX_ALTREP_REG_ENTRY_builtin_Vec_Option_Cow_str
1732);
1733impl_builtin_altrep_family!(
1734 Vec<crate::ffi::Rcomplex>,
1735 complex,
1736 dataptr,
1737 __mx_altrep_reg_builtin_Vec_Rcomplex,
1738 __MX_ALTREP_REG_ENTRY_builtin_Vec_Rcomplex
1739);
1740
1741impl_builtin_altrep_family!(
1743 std::ops::Range<i32>,
1744 integer,
1745 materializing,
1746 __mx_altrep_reg_builtin_Range_i32,
1747 __MX_ALTREP_REG_ENTRY_builtin_Range_i32
1748);
1749impl_builtin_altrep_family!(
1750 std::ops::Range<i64>,
1751 integer,
1752 materializing,
1753 __mx_altrep_reg_builtin_Range_i64,
1754 __MX_ALTREP_REG_ENTRY_builtin_Range_i64
1755);
1756impl_builtin_altrep_family!(
1757 std::ops::Range<f64>,
1758 real,
1759 materializing,
1760 __mx_altrep_reg_builtin_Range_f64,
1761 __MX_ALTREP_REG_ENTRY_builtin_Range_f64
1762);
1763impl_builtin_altrep_family!(
1772 Box<[i32]>,
1773 integer,
1774 dataptr,
1775 __mx_altrep_reg_builtin_Box_i32,
1776 __MX_ALTREP_REG_ENTRY_builtin_Box_i32
1777);
1778impl_builtin_altrep_family!(
1779 Box<[f64]>,
1780 real,
1781 dataptr,
1782 __mx_altrep_reg_builtin_Box_f64,
1783 __MX_ALTREP_REG_ENTRY_builtin_Box_f64
1784);
1785impl_builtin_altrep_family!(
1786 Box<[bool]>,
1787 logical,
1788 materializing,
1789 __mx_altrep_reg_builtin_Box_bool,
1790 __MX_ALTREP_REG_ENTRY_builtin_Box_bool
1791);
1792impl_builtin_altrep_family!(
1793 Box<[u8]>,
1794 raw,
1795 dataptr,
1796 __mx_altrep_reg_builtin_Box_u8,
1797 __MX_ALTREP_REG_ENTRY_builtin_Box_u8
1798);
1799impl_builtin_altrep_family!(
1800 Box<[String]>,
1801 string,
1802 dataptr,
1803 __mx_altrep_reg_builtin_Box_String,
1804 __MX_ALTREP_REG_ENTRY_builtin_Box_String
1805);
1806impl_builtin_altrep_family!(
1807 Box<[crate::ffi::Rcomplex]>,
1808 complex,
1809 dataptr,
1810 __mx_altrep_reg_builtin_Box_Rcomplex,
1811 __MX_ALTREP_REG_ENTRY_builtin_Box_Rcomplex
1812);
1813
1814impl_builtin_altrep_family!(
1817 std::borrow::Cow<'static, [i32]>,
1818 integer,
1819 dataptr,
1820 __mx_altrep_reg_builtin_Cow_i32,
1821 __MX_ALTREP_REG_ENTRY_builtin_Cow_i32
1822);
1823impl_builtin_altrep_family!(
1824 std::borrow::Cow<'static, [f64]>,
1825 real,
1826 dataptr,
1827 __mx_altrep_reg_builtin_Cow_f64,
1828 __MX_ALTREP_REG_ENTRY_builtin_Cow_f64
1829);
1830impl_builtin_altrep_family!(
1831 std::borrow::Cow<'static, [u8]>,
1832 raw,
1833 dataptr,
1834 __mx_altrep_reg_builtin_Cow_u8,
1835 __MX_ALTREP_REG_ENTRY_builtin_Cow_u8
1836);
1837impl_builtin_altrep_family!(
1838 std::borrow::Cow<'static, [crate::ffi::Rcomplex]>,
1839 complex,
1840 dataptr,
1841 __mx_altrep_reg_builtin_Cow_Rcomplex,
1842 __MX_ALTREP_REG_ENTRY_builtin_Cow_Rcomplex
1843);
1844
1845macro_rules! impl_altrep_array_numeric {
1857 (
1858 elem = $elem:ty,
1859 data_trait = $data_trait:path,
1860 alt_trait = $alt_trait:path,
1861 rbase = $rbase:expr,
1862 make_class_fn = $make_class_fn:path,
1863 install_family_fn = $install_family_fn:ident
1864 $(, extra { $($extra:tt)* } )?
1865 $(,)?
1866 ) => {
1867 impl<const N: usize> crate::altrep_traits::Altrep for [$elem; N] {
1868 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1869 let data = unsafe {
1870 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1871 };
1872 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1873 }
1874 }
1875
1876 impl<const N: usize> crate::altrep_traits::AltVec for [$elem; N] {
1877 const HAS_DATAPTR: bool = true;
1878
1879 fn dataptr(x: crate::ffi::SEXP, _writable: bool) -> *mut core::ffi::c_void {
1880 let data = unsafe {
1881 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
1882 };
1883 data.as_mut_ptr().cast::<core::ffi::c_void>()
1884 }
1885 }
1886
1887 impl<const N: usize> $alt_trait for [$elem; N] {
1888 const HAS_ELT: bool = true;
1889
1890 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> $elem {
1891 let data = unsafe {
1892 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1893 };
1894 <[$elem; N] as $data_trait>::elt(data, i.max(0) as usize)
1895 }
1896
1897 const HAS_GET_REGION: bool = true;
1898
1899 fn get_region(
1900 x: crate::ffi::SEXP,
1901 start: crate::ffi::R_xlen_t,
1902 len: crate::ffi::R_xlen_t,
1903 buf: &mut [$elem],
1904 ) -> crate::ffi::R_xlen_t {
1905 if start < 0 || len <= 0 {
1906 return 0;
1907 }
1908 let data = unsafe {
1909 <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
1910 };
1911 <[$elem; N] as $data_trait>::get_region(data, start as usize, len as usize, buf)
1912 as crate::ffi::R_xlen_t
1913 }
1914
1915 $($($extra)*)?
1916 }
1917
1918 impl<const N: usize> crate::altrep_data::InferBase for [$elem; N] {
1919 const BASE: crate::altrep::RBase = $rbase;
1920
1921 unsafe fn make_class(
1922 class_name: *const i8,
1923 pkg_name: *const i8,
1924 ) -> crate::ffi::altrep::R_altrep_class_t {
1925 let cls = unsafe { $make_class_fn(class_name, pkg_name, crate::altrep_dll_info()) };
1926 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
1927 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
1928 }
1929
1930 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
1931 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
1932 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
1933 unsafe { crate::altrep_bridge::$install_family_fn::<Self>(cls) };
1934 }
1935 }
1936 };
1937}
1938
1939macro_rules! altrep_array_no_na {
1941 ($elem:ty, $data_trait:path) => {
1942 const HAS_NO_NA: bool = true;
1943
1944 fn no_na(x: crate::ffi::SEXP) -> i32 {
1945 let data =
1946 unsafe { <[$elem; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1947 <[$elem; N] as $data_trait>::no_na(data)
1948 .map(i32::from)
1949 .unwrap_or(0)
1950 }
1951 };
1952}
1953
1954impl_altrep_array_numeric!(
1955 elem = i32,
1956 data_trait = crate::altrep_data::AltIntegerData,
1957 alt_trait = crate::altrep_traits::AltInteger,
1958 rbase = crate::altrep::RBase::Int,
1959 make_class_fn = crate::ffi::altrep::R_make_altinteger_class,
1960 install_family_fn = install_int,
1961 extra { altrep_array_no_na!(i32, crate::altrep_data::AltIntegerData); },
1962);
1963impl_altrep_array_numeric!(
1964 elem = f64,
1965 data_trait = crate::altrep_data::AltRealData,
1966 alt_trait = crate::altrep_traits::AltReal,
1967 rbase = crate::altrep::RBase::Real,
1968 make_class_fn = crate::ffi::altrep::R_make_altreal_class,
1969 install_family_fn = install_real,
1970 extra { altrep_array_no_na!(f64, crate::altrep_data::AltRealData); },
1971);
1972impl_altrep_array_numeric!(
1973 elem = u8,
1974 data_trait = crate::altrep_data::AltRawData,
1975 alt_trait = crate::altrep_traits::AltRaw,
1976 rbase = crate::altrep::RBase::Raw,
1977 make_class_fn = crate::ffi::altrep::R_make_altraw_class,
1978 install_family_fn = install_raw,
1979);
1980impl_altrep_array_numeric!(
1981 elem = crate::ffi::Rcomplex,
1982 data_trait = crate::altrep_data::AltComplexData,
1983 alt_trait = crate::altrep_traits::AltComplex,
1984 rbase = crate::altrep::RBase::Complex,
1985 make_class_fn = crate::ffi::altrep::R_make_altcomplex_class,
1986 install_family_fn = install_cplx,
1987);
1988
1989impl<const N: usize> crate::altrep_traits::Altrep for [bool; N] {
1991 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
1992 let data =
1993 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
1994 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
1995 }
1996}
1997
1998impl<const N: usize> crate::altrep_traits::AltVec for [bool; N] {}
1999
2000impl<const N: usize> crate::altrep_traits::AltLogical for [bool; N] {
2001 const HAS_ELT: bool = true;
2002
2003 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
2004 let data =
2005 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2006 <[bool; N] as crate::altrep_data::AltLogicalData>::elt(data, i.max(0) as usize).to_r_int()
2007 }
2008
2009 const HAS_NO_NA: bool = true;
2010
2011 fn no_na(x: crate::ffi::SEXP) -> i32 {
2012 let data =
2013 unsafe { <[bool; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2014 <[bool; N] as crate::altrep_data::AltLogicalData>::no_na(data)
2015 .map(i32::from)
2016 .unwrap_or(0)
2017 }
2018}
2019
2020impl<const N: usize> crate::altrep_data::InferBase for [bool; N] {
2021 const BASE: crate::altrep::RBase = crate::altrep::RBase::Logical;
2022
2023 unsafe fn make_class(
2024 class_name: *const i8,
2025 pkg_name: *const i8,
2026 ) -> crate::ffi::altrep::R_altrep_class_t {
2027 let cls = unsafe {
2028 crate::ffi::altrep::R_make_altlogical_class(
2029 class_name,
2030 pkg_name,
2031 crate::altrep_dll_info(),
2032 )
2033 };
2034 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
2035 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
2036 }
2037
2038 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
2039 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
2040 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
2041 unsafe { crate::altrep_bridge::install_lgl::<Self>(cls) };
2042 }
2043}
2044
2045impl<const N: usize> crate::altrep_traits::Altrep for [String; N] {
2047 const GUARD: crate::altrep_traits::AltrepGuard = crate::altrep_traits::AltrepGuard::RUnwind;
2048
2049 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2050 let data =
2051 unsafe { <[String; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2052 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2053 }
2054}
2055
2056impl<const N: usize> crate::altrep_traits::AltVec for [String; N] {}
2057
2058impl<const N: usize> crate::altrep_traits::AltString for [String; N] {
2059 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::SEXP {
2060 let data =
2061 unsafe { <[String; N] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2062 match <[String; N] as crate::altrep_data::AltStringData>::elt(data, i.max(0) as usize) {
2063 Some(s) => unsafe { checked_mkchar(s) },
2064 None => crate::ffi::SEXP::na_string(),
2065 }
2066 }
2067}
2068
2069impl<const N: usize> crate::altrep_data::InferBase for [String; N] {
2070 const BASE: crate::altrep::RBase = crate::altrep::RBase::String;
2071
2072 unsafe fn make_class(
2073 class_name: *const i8,
2074 pkg_name: *const i8,
2075 ) -> crate::ffi::altrep::R_altrep_class_t {
2076 let cls = unsafe {
2077 crate::ffi::altrep::R_make_altstring_class(
2078 class_name,
2079 pkg_name,
2080 crate::altrep_dll_info(),
2081 )
2082 };
2083 let name = unsafe { core::ffi::CStr::from_ptr(class_name) };
2084 crate::altrep::validate_altrep_class(cls, name, Self::BASE)
2085 }
2086
2087 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
2088 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
2089 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
2090 unsafe { crate::altrep_bridge::install_str::<Self>(cls) };
2091 }
2092}
2093impl crate::altrep_traits::Altrep for &'static [i32] {
2107 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2108 let data =
2109 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2110 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2111 }
2112}
2113
2114impl crate::altrep_traits::AltVec for &'static [i32] {
2115 const HAS_DATAPTR: bool = true;
2116
2117 fn dataptr(x: crate::ffi::SEXP, writable: bool) -> *mut std::ffi::c_void {
2118 assert!(
2120 !writable,
2121 "cannot get writable DATAPTR for static ALTREP data"
2122 );
2123 let data =
2124 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2125 data.as_ptr().cast::<std::ffi::c_void>().cast_mut()
2126 }
2127
2128 const HAS_DATAPTR_OR_NULL: bool = true;
2129
2130 fn dataptr_or_null(x: crate::ffi::SEXP) -> *const std::ffi::c_void {
2131 let data =
2132 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2133 data.as_ptr().cast::<std::ffi::c_void>()
2134 }
2135}
2136
2137impl crate::altrep_traits::AltInteger for &'static [i32] {
2138 const HAS_ELT: bool = true;
2139
2140 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
2141 let data =
2142 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2143 crate::altrep_data::AltIntegerData::elt(data, i.max(0) as usize)
2144 }
2145
2146 const HAS_GET_REGION: bool = true;
2147
2148 fn get_region(
2149 x: crate::ffi::SEXP,
2150 start: crate::ffi::R_xlen_t,
2151 len: crate::ffi::R_xlen_t,
2152 buf: &mut [i32],
2153 ) -> crate::ffi::R_xlen_t {
2154 if start < 0 || len <= 0 {
2155 return 0;
2156 }
2157 let data =
2158 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2159 let len = len as usize;
2160 crate::altrep_data::AltIntegerData::get_region(data, start as usize, len, buf)
2161 as crate::ffi::R_xlen_t
2162 }
2163
2164 const HAS_NO_NA: bool = true;
2165
2166 fn no_na(x: crate::ffi::SEXP) -> i32 {
2167 let data =
2168 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2169 crate::altrep_data::AltIntegerData::no_na(data)
2170 .map(|b| if b { 1 } else { 0 })
2171 .unwrap_or(0)
2172 }
2173
2174 const HAS_SUM: bool = true;
2175
2176 fn sum(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
2178 let data =
2179 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2180 crate::altrep_data::AltIntegerData::sum(data, narm)
2181 .map(|s| {
2182 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
2183 crate::ffi::SEXP::scalar_integer(s as i32)
2184 } else {
2185 crate::ffi::SEXP::scalar_real(s as f64)
2186 }
2187 })
2188 .unwrap_or(crate::ffi::SEXP::null())
2189 }
2190
2191 const HAS_MIN: bool = true;
2192
2193 fn min(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
2194 let data =
2195 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2196 crate::altrep_data::AltIntegerData::min(data, narm)
2197 .map(crate::ffi::SEXP::scalar_integer)
2198 .unwrap_or(crate::ffi::SEXP::null())
2199 }
2200
2201 const HAS_MAX: bool = true;
2202
2203 fn max(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
2204 let data =
2205 unsafe { <&'static [i32] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2206 crate::altrep_data::AltIntegerData::max(data, narm)
2207 .map(crate::ffi::SEXP::scalar_integer)
2208 .unwrap_or(crate::ffi::SEXP::null())
2209 }
2210}
2211
2212crate::impl_inferbase_integer!(&'static [i32]);
2213
2214impl crate::altrep_traits::Altrep for &'static [f64] {
2216 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2217 let data =
2218 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2219 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2220 }
2221}
2222
2223impl crate::altrep_traits::AltVec for &'static [f64] {
2224 const HAS_DATAPTR: bool = true;
2225
2226 fn dataptr(x: crate::ffi::SEXP, writable: bool) -> *mut std::ffi::c_void {
2227 assert!(
2228 !writable,
2229 "cannot get writable DATAPTR for static ALTREP data"
2230 );
2231 let data =
2232 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2233 data.as_ptr().cast::<std::ffi::c_void>().cast_mut()
2234 }
2235
2236 const HAS_DATAPTR_OR_NULL: bool = true;
2237
2238 fn dataptr_or_null(x: crate::ffi::SEXP) -> *const std::ffi::c_void {
2239 let data =
2240 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2241 data.as_ptr().cast::<std::ffi::c_void>()
2242 }
2243}
2244
2245impl crate::altrep_traits::AltReal for &'static [f64] {
2246 const HAS_ELT: bool = true;
2247
2248 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> f64 {
2249 let data =
2250 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2251 crate::altrep_data::AltRealData::elt(data, i.max(0) as usize)
2252 }
2253
2254 const HAS_GET_REGION: bool = true;
2255
2256 fn get_region(
2257 x: crate::ffi::SEXP,
2258 start: crate::ffi::R_xlen_t,
2259 len: crate::ffi::R_xlen_t,
2260 buf: &mut [f64],
2261 ) -> crate::ffi::R_xlen_t {
2262 if start < 0 || len <= 0 {
2263 return 0;
2264 }
2265 let data =
2266 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2267 let len = len as usize;
2268 crate::altrep_data::AltRealData::get_region(data, start as usize, len, buf)
2269 as crate::ffi::R_xlen_t
2270 }
2271
2272 const HAS_NO_NA: bool = true;
2273
2274 fn no_na(x: crate::ffi::SEXP) -> i32 {
2275 let data =
2276 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2277 crate::altrep_data::AltRealData::no_na(data)
2278 .map(|b| if b { 1 } else { 0 })
2279 .unwrap_or(0)
2280 }
2281
2282 const HAS_SUM: bool = true;
2283
2284 fn sum(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
2286 let data =
2287 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2288 crate::altrep_data::AltRealData::sum(data, narm)
2289 .map(crate::ffi::SEXP::scalar_real)
2290 .unwrap_or(crate::ffi::SEXP::null())
2291 }
2292
2293 const HAS_MIN: bool = true;
2294
2295 fn min(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
2296 let data =
2297 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2298 crate::altrep_data::AltRealData::min(data, narm)
2299 .map(crate::ffi::SEXP::scalar_real)
2300 .unwrap_or(crate::ffi::SEXP::null())
2301 }
2302
2303 const HAS_MAX: bool = true;
2304
2305 fn max(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
2306 let data =
2307 unsafe { <&'static [f64] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2308 crate::altrep_data::AltRealData::max(data, narm)
2309 .map(crate::ffi::SEXP::scalar_real)
2310 .unwrap_or(crate::ffi::SEXP::null())
2311 }
2312}
2313
2314crate::impl_inferbase_real!(&'static [f64]);
2315
2316impl crate::altrep_traits::Altrep for &'static [bool] {
2318 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2319 let data = unsafe {
2320 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2321 };
2322 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2323 }
2324}
2325
2326impl crate::altrep_traits::AltVec for &'static [bool] {}
2327
2328impl crate::altrep_traits::AltLogical for &'static [bool] {
2329 const HAS_ELT: bool = true;
2330
2331 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
2332 let data = unsafe {
2333 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2334 };
2335 crate::altrep_data::AltLogicalData::elt(data, i.max(0) as usize).to_r_int()
2336 }
2337
2338 const HAS_NO_NA: bool = true;
2339
2340 fn no_na(x: crate::ffi::SEXP) -> i32 {
2341 let data = unsafe {
2342 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2343 };
2344 crate::altrep_data::AltLogicalData::no_na(data)
2345 .map(|b| if b { 1 } else { 0 })
2346 .unwrap_or(0)
2347 }
2348
2349 const HAS_SUM: bool = true;
2350
2351 fn sum(x: crate::ffi::SEXP, narm: bool) -> crate::ffi::SEXP {
2353 let data = unsafe {
2354 <&'static [bool] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2355 };
2356 crate::altrep_data::AltLogicalData::sum(data, narm)
2357 .map(|s| {
2358 if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
2359 crate::ffi::SEXP::scalar_integer(s as i32)
2360 } else {
2361 crate::ffi::SEXP::scalar_real(s as f64)
2362 }
2363 })
2364 .unwrap_or(crate::ffi::SEXP::null())
2365 }
2366}
2367
2368crate::impl_inferbase_logical!(&'static [bool]);
2369
2370impl crate::altrep_traits::Altrep for &'static [u8] {
2372 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2373 let data =
2374 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2375 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2376 }
2377}
2378
2379impl crate::altrep_traits::AltVec for &'static [u8] {
2380 const HAS_DATAPTR: bool = true;
2381
2382 fn dataptr(x: crate::ffi::SEXP, writable: bool) -> *mut std::ffi::c_void {
2383 assert!(
2384 !writable,
2385 "cannot get writable DATAPTR for static ALTREP data"
2386 );
2387 let data =
2388 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2389 data.as_ptr().cast::<std::ffi::c_void>().cast_mut()
2390 }
2391
2392 const HAS_DATAPTR_OR_NULL: bool = true;
2393
2394 fn dataptr_or_null(x: crate::ffi::SEXP) -> *const std::ffi::c_void {
2395 let data =
2396 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2397 data.as_ptr().cast::<std::ffi::c_void>()
2398 }
2399}
2400
2401impl crate::altrep_traits::AltRaw for &'static [u8] {
2402 const HAS_ELT: bool = true;
2403
2404 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::Rbyte {
2405 let data =
2406 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2407 crate::altrep_data::AltRawData::elt(data, i.max(0) as usize)
2408 }
2409
2410 const HAS_GET_REGION: bool = true;
2411
2412 fn get_region(
2413 x: crate::ffi::SEXP,
2414 start: crate::ffi::R_xlen_t,
2415 len: crate::ffi::R_xlen_t,
2416 buf: &mut [u8],
2417 ) -> crate::ffi::R_xlen_t {
2418 if start < 0 || len <= 0 {
2419 return 0;
2420 }
2421 let data =
2422 unsafe { <&'static [u8] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
2423 let len = len as usize;
2424 crate::altrep_data::AltRawData::get_region(data, start as usize, len, buf)
2425 as crate::ffi::R_xlen_t
2426 }
2427}
2428
2429crate::impl_inferbase_raw!(&'static [u8]);
2430
2431impl crate::altrep_traits::Altrep for &'static [String] {
2433 const GUARD: crate::altrep_traits::AltrepGuard = crate::altrep_traits::AltrepGuard::RUnwind;
2435
2436 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2437 let data = unsafe {
2438 <&'static [String] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2439 };
2440 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2441 }
2442}
2443
2444impl crate::altrep_traits::AltVec for &'static [String] {}
2445
2446impl crate::altrep_traits::AltString for &'static [String] {
2447 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::SEXP {
2448 let data = unsafe {
2449 <&'static [String] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2450 };
2451 match crate::altrep_data::AltStringData::elt(data, i.max(0) as usize) {
2452 Some(s) => unsafe { checked_mkchar(s) },
2453 None => crate::ffi::SEXP::na_string(),
2454 }
2455 }
2456
2457 const HAS_NO_NA: bool = true;
2458
2459 fn no_na(x: crate::ffi::SEXP) -> i32 {
2460 let data = unsafe {
2461 <&'static [String] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2462 };
2463 crate::altrep_data::AltStringData::no_na(data)
2464 .map(|b| if b { 1 } else { 0 })
2465 .unwrap_or(0)
2466 }
2467}
2468
2469crate::impl_inferbase_string!(&'static [String]);
2470
2471impl crate::altrep_traits::Altrep for &'static [&'static str] {
2473 const GUARD: crate::altrep_traits::AltrepGuard = crate::altrep_traits::AltrepGuard::RUnwind;
2475
2476 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
2477 let data = unsafe {
2478 <&'static [&'static str] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2479 };
2480 crate::altrep_data::AltrepLen::len(data) as crate::ffi::R_xlen_t
2481 }
2482}
2483
2484impl crate::altrep_traits::AltVec for &'static [&'static str] {}
2485
2486impl crate::altrep_traits::AltString for &'static [&'static str] {
2487 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::SEXP {
2488 let data = unsafe {
2489 <&'static [&'static str] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2490 };
2491 match crate::altrep_data::AltStringData::elt(data, i.max(0) as usize) {
2492 Some(s) => unsafe { checked_mkchar(s) },
2493 None => crate::ffi::SEXP::na_string(),
2494 }
2495 }
2496
2497 const HAS_NO_NA: bool = true;
2498
2499 fn no_na(x: crate::ffi::SEXP) -> i32 {
2500 let data = unsafe {
2501 <&'static [&'static str] as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
2502 };
2503 crate::altrep_data::AltStringData::no_na(data)
2504 .map(|b| if b { 1 } else { 0 })
2505 .unwrap_or(0)
2506 }
2507}
2508
2509crate::impl_inferbase_string!(&'static [&'static str]);
2510use crate::altrep::RegisterAltrep;
2527
2528macro_rules! impl_register_altrep_builtin {
2530 ($ty:ty, $class_name:expr) => {
2531 impl RegisterAltrep for $ty {
2532 fn get_or_init_class() -> crate::ffi::altrep::R_altrep_class_t {
2533 use std::sync::OnceLock;
2534 static CLASS: OnceLock<crate::ffi::altrep::R_altrep_class_t> = OnceLock::new();
2535 *CLASS.get_or_init(|| {
2536 const CLASS_NAME: &[u8] = concat!($class_name, "\0").as_bytes();
2538 let cls = unsafe {
2539 <$ty as crate::altrep_data::InferBase>::make_class(
2540 CLASS_NAME.as_ptr().cast::<std::ffi::c_char>(),
2541 crate::AltrepPkgName::as_ptr(),
2542 )
2543 };
2544 unsafe {
2545 <$ty as crate::altrep_data::InferBase>::install_methods(cls);
2546 }
2547 cls
2548 })
2549 }
2550 }
2551 };
2552}
2553
2554impl_register_altrep_builtin!(Vec<i32>, "Vec_i32");
2556impl_register_altrep_builtin!(Vec<f64>, "Vec_f64");
2557impl_register_altrep_builtin!(Vec<bool>, "Vec_bool");
2558impl_register_altrep_builtin!(Vec<u8>, "Vec_u8");
2559impl_register_altrep_builtin!(Vec<String>, "Vec_String");
2560impl_register_altrep_builtin!(Vec<Option<String>>, "Vec_Option_String");
2561impl_register_altrep_builtin!(Vec<crate::ffi::Rcomplex>, "Vec_Rcomplex");
2562
2563impl_register_altrep_builtin!(std::ops::Range<i32>, "Range_i32");
2565impl_register_altrep_builtin!(std::ops::Range<i64>, "Range_i64");
2566impl_register_altrep_builtin!(std::ops::Range<f64>, "Range_f64");
2567
2568impl_register_altrep_builtin!(Box<[i32]>, "Box_i32");
2570impl_register_altrep_builtin!(Box<[f64]>, "Box_f64");
2571impl_register_altrep_builtin!(Box<[bool]>, "Box_bool");
2572impl_register_altrep_builtin!(Box<[u8]>, "Box_u8");
2573impl_register_altrep_builtin!(Box<[String]>, "Box_String");
2574impl_register_altrep_builtin!(Box<[crate::ffi::Rcomplex]>, "Box_Rcomplex");
2575
2576impl_register_altrep_builtin!(std::borrow::Cow<'static, [i32]>, "Cow_i32");
2578impl_register_altrep_builtin!(std::borrow::Cow<'static, [f64]>, "Cow_f64");
2579impl_register_altrep_builtin!(std::borrow::Cow<'static, [u8]>, "Cow_u8");
2580impl_register_altrep_builtin!(
2581 std::borrow::Cow<'static, [crate::ffi::Rcomplex]>,
2582 "Cow_Rcomplex"
2583);
2584
2585impl_register_altrep_builtin!(Vec<std::borrow::Cow<'static, str>>, "Vec_Cow_str");
2587impl_register_altrep_builtin!(
2588 Vec<Option<std::borrow::Cow<'static, str>>>,
2589 "Vec_Option_Cow_str"
2590);
2591