Skip to main content

miniextendr_api/altrep_data/
macros.rs

1//! Convenience macros for implementing `InferBase`.
2//!
3//! The parametric `__impl_inferbase!` macro provides the shared implementation.
4//! Each `impl_inferbase_*!` macro is a thin wrapper that passes family-specific
5//! parameters (`RBase` variant, `R_make_alt*_class` function, `install_*` function).
6//!
7//! These macros are used by the `#[derive(Altrep)]` proc macro and by the
8//! built-in type implementations in `super::builtins`.
9
10/// Parametric implementation of `InferBase` for any ALTREP family.
11///
12/// Takes the type, RBase variant, R_make_alt*_class function, and family installer.
13#[macro_export]
14#[doc(hidden)]
15macro_rules! __impl_inferbase {
16    ($ty:ty, $base:ident, $make_fn:path, $install_fn:ident) => {
17        impl $crate::altrep_data::InferBase for $ty {
18            const BASE: $crate::altrep::RBase = $crate::altrep::RBase::$base;
19
20            unsafe fn make_class(
21                class_name: *const i8,
22                pkg_name: *const i8,
23            ) -> $crate::ffi::altrep::R_altrep_class_t {
24                // Use stored DllInfo from package_init. R needs this to find
25                // the ALTREP class during cross-session deserialization (readRDS).
26                let dll = $crate::altrep_dll_info();
27                let cls = unsafe { $make_fn(class_name, pkg_name, dll) };
28                let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
29                $crate::altrep::validate_altrep_class(cls, name, $crate::altrep::RBase::$base)
30            }
31
32            unsafe fn install_methods(cls: $crate::ffi::altrep::R_altrep_class_t) {
33                unsafe { $crate::altrep_bridge::install_base::<$ty>(cls) };
34                unsafe { $crate::altrep_bridge::install_vec::<$ty>(cls) };
35                unsafe { $crate::altrep_bridge::$install_fn::<$ty>(cls) };
36            }
37        }
38    };
39}
40
41/// Implement `InferBase` for an integer ALTREP data type.
42#[macro_export]
43macro_rules! impl_inferbase_integer {
44    ($ty:ty) => {
45        $crate::__impl_inferbase!(
46            $ty,
47            Int,
48            $crate::ffi::altrep::R_make_altinteger_class,
49            install_int
50        );
51    };
52}
53
54/// Implement `InferBase` for a real ALTREP data type.
55#[macro_export]
56macro_rules! impl_inferbase_real {
57    ($ty:ty) => {
58        $crate::__impl_inferbase!(
59            $ty,
60            Real,
61            $crate::ffi::altrep::R_make_altreal_class,
62            install_real
63        );
64    };
65}
66
67/// Implement `InferBase` for a logical ALTREP data type.
68#[macro_export]
69macro_rules! impl_inferbase_logical {
70    ($ty:ty) => {
71        $crate::__impl_inferbase!(
72            $ty,
73            Logical,
74            $crate::ffi::altrep::R_make_altlogical_class,
75            install_lgl
76        );
77    };
78}
79
80/// Implement `InferBase` for a raw ALTREP data type.
81#[macro_export]
82macro_rules! impl_inferbase_raw {
83    ($ty:ty) => {
84        $crate::__impl_inferbase!(
85            $ty,
86            Raw,
87            $crate::ffi::altrep::R_make_altraw_class,
88            install_raw
89        );
90    };
91}
92
93/// Implement `InferBase` for a string ALTREP data type.
94#[macro_export]
95macro_rules! impl_inferbase_string {
96    ($ty:ty) => {
97        $crate::__impl_inferbase!(
98            $ty,
99            String,
100            $crate::ffi::altrep::R_make_altstring_class,
101            install_str
102        );
103    };
104}
105
106/// Implement `InferBase` for a complex ALTREP data type.
107#[macro_export]
108macro_rules! impl_inferbase_complex {
109    ($ty:ty) => {
110        $crate::__impl_inferbase!(
111            $ty,
112            Complex,
113            $crate::ffi::altrep::R_make_altcomplex_class,
114            install_cplx
115        );
116    };
117}
118
119/// Implement `InferBase` for a list ALTREP data type.
120#[macro_export]
121macro_rules! impl_inferbase_list {
122    ($ty:ty) => {
123        $crate::__impl_inferbase!(
124            $ty,
125            List,
126            $crate::ffi::altrep::R_make_altlist_class,
127            install_list
128        );
129    };
130}
131
132// region: Logical enum tests
133#[cfg(test)]
134mod tests;
135// endregion