Skip to main content

miniextendr_api/altrep_impl/
builtins.rs

1//! Built-in ALTREP class instantiations for `Vec<T>`, `Box<[T]>`, `Cow<T>`,
2//! and `Range<T>`.
3//!
4//! This file contains two crate-private declarative macros that are *not*
5//! `#[macro_export]`ed: `impl_builtin_altrep_family!` (emits the family impl
6//! plus linkme registration) and `impl_register_altrep_builtin!` (emits the
7//! `RegisterAltrep` impl with the cached `OnceLock` class handle).
8//!
9//! User crates do not invoke these macros directly — they call
10//! `impl_alt<family>_from_data!` plus a hand-rolled `RegisterAltrep` impl, or
11//! use the `#[derive(Altrep<Family>)]` proc-macro which emits the equivalent
12//! code.
13
14// region: Meta-macros for built-in ALTREP family instantiation
15//
16// `impl_builtin_altrep_family!` is a single declarative meta-macro that maps a
17// (type, family, dataptr-mode, sym) 4-tuple to the correct per-family
18// `impl_alt*_from_data!` call AND emits a linkme `MX_ALTREP_REGISTRATIONS` entry
19// so the class is registered at `R_init_*` time (no hand-enumerated list needed).
20//
21// The `$sym:ident` parameter is a unique snake_case identifier used as the suffix
22// for the `#[no_mangle]` registration fn and the linkme static.  It must be unique
23// across all call sites — naming convention: `<container>_<elem>` (e.g. `Vec_i32`,
24// `Box_bool`, `Cow_str`, `Range_i32`).
25//
26// ## Families
27//
28// | Token     | Delegates to               |
29// |-----------|----------------------------|
30// | `integer` | `impl_altinteger_from_data!` |
31// | `real`    | `impl_altreal_from_data!`    |
32// | `logical` | `impl_altlogical_from_data!` |
33// | `raw`     | `impl_altraw_from_data!`     |
34// | `string`  | `impl_altstring_from_data!`  |
35// | `complex` | `impl_altcomplex_from_data!` |
36//
37// ## Dataptr modes
38//
39// | Token         | Meaning                                                     |
40// |---------------|-------------------------------------------------------------|
41// | `dataptr`     | Type has a direct contiguous pointer (`RNativeType` backed) |
42// | `materializing` | No direct pointer; materializes into data2 on first access  |
43//
44// The `materializing` arm expands to `($ty, serialize)` in the underlying
45// per-family macro — the `($ty, serialize)` arm IS the materializing path
46// (it routes through `__impl_altvec_<family>_dataptr!` which provides a
47// trivial `AltrepDataptr<T>` returning `None`, falling through to data2
48// materialisation for bool→i32 conversion, Range compute-on-access, etc.).
49// Both arms preserve `const GUARD = AltrepGuard::RUnwind` — the default from
50// `__impl_altrep_base!`'s default and `with_serialize` arms.
51//
52// ## Corner cases NOT handled by this macro
53//
54// - `[T; N]` const-generic arrays: use const generics (`impl<const N>`); left in the
55//   "Array implementations" region below.
56// - `&'static [T]` static slices: unique lifetime + writable-assert pattern; left in
57//   the "Static slice implementations" region below.
58
59/// Generate ALTREP trait impls AND a linkme `MX_ALTREP_REGISTRATIONS` entry for a
60/// builtin type.
61///
62/// ## Arguments
63///
64/// - `$ty:ty` — the builtin container type (e.g. `Vec<i32>`, `Box<[f64]>`)
65/// - `$family:ident` — ALTREP family token: `integer`, `real`, `logical`, `raw`,
66///   `string`, or `complex`
67/// - `$mode:ident` — dataptr mode: `dataptr` or `materializing`
68/// - `$reg_fn:ident` — unique `#[no_mangle]` name for the registration fn
69///   (convention: `__mx_altrep_reg_builtin_<sym>`)
70/// - `$entry_ident:ident` — unique name for the linkme static
71///   (convention: `__MX_ALTREP_REG_ENTRY_builtin_<sym>`)
72///
73/// Both identifier arguments must be globally unique across all call sites.
74/// The registration fn is always emitted; the `#[distributed_slice]` attribute
75/// is guarded by `cfg_attr(not(target_arch = "wasm32"), ...)` so linkme's
76/// compile-error arm is not reached on wasm32 targets.
77#[doc(hidden)]
78macro_rules! impl_builtin_altrep_family {
79    // dataptr arm — type has a direct contiguous native pointer
80    ($ty:ty, integer, dataptr, $reg_fn:ident, $entry_ident:ident) => {
81        $crate::impl_altinteger_from_data!($ty, dataptr, serialize);
82        #[doc(hidden)]
83        #[unsafe(no_mangle)]
84        pub extern "C" fn $reg_fn() {
85            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
86        }
87        #[cfg_attr(
88                    not(target_arch = "wasm32"),
89                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
90                    linkme(crate = $crate::linkme)
91                )]
92        #[doc(hidden)]
93        #[allow(non_upper_case_globals)]
94        static $entry_ident: $crate::registry::AltrepRegistration =
95            $crate::registry::AltrepRegistration {
96                register: $reg_fn,
97                symbol: stringify!($reg_fn),
98            };
99    };
100    ($ty:ty, real, dataptr, $reg_fn:ident, $entry_ident:ident) => {
101        $crate::impl_altreal_from_data!($ty, dataptr, serialize);
102        #[doc(hidden)]
103        #[unsafe(no_mangle)]
104        pub extern "C" fn $reg_fn() {
105            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
106        }
107        #[cfg_attr(
108                    not(target_arch = "wasm32"),
109                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
110                    linkme(crate = $crate::linkme)
111                )]
112        #[doc(hidden)]
113        #[allow(non_upper_case_globals)]
114        static $entry_ident: $crate::registry::AltrepRegistration =
115            $crate::registry::AltrepRegistration {
116                register: $reg_fn,
117                symbol: stringify!($reg_fn),
118            };
119    };
120    ($ty:ty, logical, dataptr, $reg_fn:ident, $entry_ident:ident) => {
121        $crate::impl_altlogical_from_data!($ty, dataptr, serialize);
122        #[doc(hidden)]
123        #[unsafe(no_mangle)]
124        pub extern "C" fn $reg_fn() {
125            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
126        }
127        #[cfg_attr(
128                    not(target_arch = "wasm32"),
129                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
130                    linkme(crate = $crate::linkme)
131                )]
132        #[doc(hidden)]
133        #[allow(non_upper_case_globals)]
134        static $entry_ident: $crate::registry::AltrepRegistration =
135            $crate::registry::AltrepRegistration {
136                register: $reg_fn,
137                symbol: stringify!($reg_fn),
138            };
139    };
140    ($ty:ty, raw, dataptr, $reg_fn:ident, $entry_ident:ident) => {
141        $crate::impl_altraw_from_data!($ty, dataptr, serialize);
142        #[doc(hidden)]
143        #[unsafe(no_mangle)]
144        pub extern "C" fn $reg_fn() {
145            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
146        }
147        #[cfg_attr(
148                    not(target_arch = "wasm32"),
149                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
150                    linkme(crate = $crate::linkme)
151                )]
152        #[doc(hidden)]
153        #[allow(non_upper_case_globals)]
154        static $entry_ident: $crate::registry::AltrepRegistration =
155            $crate::registry::AltrepRegistration {
156                register: $reg_fn,
157                symbol: stringify!($reg_fn),
158            };
159    };
160    ($ty:ty, string, dataptr, $reg_fn:ident, $entry_ident:ident) => {
161        $crate::impl_altstring_from_data!($ty, dataptr, serialize);
162        #[doc(hidden)]
163        #[unsafe(no_mangle)]
164        pub extern "C" fn $reg_fn() {
165            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
166        }
167        #[cfg_attr(
168                    not(target_arch = "wasm32"),
169                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
170                    linkme(crate = $crate::linkme)
171                )]
172        #[doc(hidden)]
173        #[allow(non_upper_case_globals)]
174        static $entry_ident: $crate::registry::AltrepRegistration =
175            $crate::registry::AltrepRegistration {
176                register: $reg_fn,
177                symbol: stringify!($reg_fn),
178            };
179    };
180    ($ty:ty, complex, dataptr, $reg_fn:ident, $entry_ident:ident) => {
181        $crate::impl_altcomplex_from_data!($ty, dataptr, serialize);
182        #[doc(hidden)]
183        #[unsafe(no_mangle)]
184        pub extern "C" fn $reg_fn() {
185            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
186        }
187        #[cfg_attr(
188                    not(target_arch = "wasm32"),
189                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
190                    linkme(crate = $crate::linkme)
191                )]
192        #[doc(hidden)]
193        #[allow(non_upper_case_globals)]
194        static $entry_ident: $crate::registry::AltrepRegistration =
195            $crate::registry::AltrepRegistration {
196                register: $reg_fn,
197                symbol: stringify!($reg_fn),
198            };
199    };
200    // materializing arm — no direct native pointer; materializes on DATAPTR access.
201    // Used for: bool (bool→i32 via LGLSXP), Range<T> (compute-on-access).
202    // Guard remains RUnwind (the default) — the underlying macros do not change it.
203    //
204    // The materializing path is the *default* arm of `impl_alt<family>_from_data!`
205    // (the per-family `__impl_altvec_<family>_dataptr!` provides a trivial
206    // `AltrepDataptr<T>` returning `None`, falling through to materialise into
207    // data2). `serialize` is added to all builtin instantiations.
208    ($ty:ty, integer, materializing, $reg_fn:ident, $entry_ident:ident) => {
209        $crate::impl_altinteger_from_data!($ty, serialize);
210        #[doc(hidden)]
211        #[unsafe(no_mangle)]
212        pub extern "C" fn $reg_fn() {
213            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
214        }
215        #[cfg_attr(
216                    not(target_arch = "wasm32"),
217                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
218                    linkme(crate = $crate::linkme)
219                )]
220        #[doc(hidden)]
221        #[allow(non_upper_case_globals)]
222        static $entry_ident: $crate::registry::AltrepRegistration =
223            $crate::registry::AltrepRegistration {
224                register: $reg_fn,
225                symbol: stringify!($reg_fn),
226            };
227    };
228    ($ty:ty, real, materializing, $reg_fn:ident, $entry_ident:ident) => {
229        $crate::impl_altreal_from_data!($ty, serialize);
230        #[doc(hidden)]
231        #[unsafe(no_mangle)]
232        pub extern "C" fn $reg_fn() {
233            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
234        }
235        #[cfg_attr(
236                    not(target_arch = "wasm32"),
237                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
238                    linkme(crate = $crate::linkme)
239                )]
240        #[doc(hidden)]
241        #[allow(non_upper_case_globals)]
242        static $entry_ident: $crate::registry::AltrepRegistration =
243            $crate::registry::AltrepRegistration {
244                register: $reg_fn,
245                symbol: stringify!($reg_fn),
246            };
247    };
248    ($ty:ty, logical, materializing, $reg_fn:ident, $entry_ident:ident) => {
249        $crate::impl_altlogical_from_data!($ty, serialize);
250        #[doc(hidden)]
251        #[unsafe(no_mangle)]
252        pub extern "C" fn $reg_fn() {
253            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
254        }
255        #[cfg_attr(
256                    not(target_arch = "wasm32"),
257                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
258                    linkme(crate = $crate::linkme)
259                )]
260        #[doc(hidden)]
261        #[allow(non_upper_case_globals)]
262        static $entry_ident: $crate::registry::AltrepRegistration =
263            $crate::registry::AltrepRegistration {
264                register: $reg_fn,
265                symbol: stringify!($reg_fn),
266            };
267    };
268    ($ty:ty, raw, materializing, $reg_fn:ident, $entry_ident:ident) => {
269        $crate::impl_altraw_from_data!($ty, serialize);
270        #[doc(hidden)]
271        #[unsafe(no_mangle)]
272        pub extern "C" fn $reg_fn() {
273            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
274        }
275        #[cfg_attr(
276                    not(target_arch = "wasm32"),
277                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
278                    linkme(crate = $crate::linkme)
279                )]
280        #[doc(hidden)]
281        #[allow(non_upper_case_globals)]
282        static $entry_ident: $crate::registry::AltrepRegistration =
283            $crate::registry::AltrepRegistration {
284                register: $reg_fn,
285                symbol: stringify!($reg_fn),
286            };
287    };
288    ($ty:ty, string, materializing, $reg_fn:ident, $entry_ident:ident) => {
289        $crate::impl_altstring_from_data!($ty, serialize);
290        #[doc(hidden)]
291        #[unsafe(no_mangle)]
292        pub extern "C" fn $reg_fn() {
293            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
294        }
295        #[cfg_attr(
296                    not(target_arch = "wasm32"),
297                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
298                    linkme(crate = $crate::linkme)
299                )]
300        #[doc(hidden)]
301        #[allow(non_upper_case_globals)]
302        static $entry_ident: $crate::registry::AltrepRegistration =
303            $crate::registry::AltrepRegistration {
304                register: $reg_fn,
305                symbol: stringify!($reg_fn),
306            };
307    };
308    ($ty:ty, complex, materializing, $reg_fn:ident, $entry_ident:ident) => {
309        $crate::impl_altcomplex_from_data!($ty, serialize);
310        #[doc(hidden)]
311        #[unsafe(no_mangle)]
312        pub extern "C" fn $reg_fn() {
313            <$ty as $crate::altrep::RegisterAltrep>::get_or_init_class();
314        }
315        #[cfg_attr(
316                    not(target_arch = "wasm32"),
317                    $crate::linkme::distributed_slice($crate::registry::MX_ALTREP_REGISTRATIONS),
318                    linkme(crate = $crate::linkme)
319                )]
320        #[doc(hidden)]
321        #[allow(non_upper_case_globals)]
322        static $entry_ident: $crate::registry::AltrepRegistration =
323            $crate::registry::AltrepRegistration {
324                register: $reg_fn,
325                symbol: stringify!($reg_fn),
326            };
327    };
328}
329
330// region: Built-in implementations for standard types
331// These implementations are provided here to satisfy the orphan rules.
332// User crates can use these types directly with delegate_data.
333//
334// All types implement AltrepSerialize; serialize is injected by the meta-macro.
335// Guard: RUnwind (default from __impl_altrep_base!'s arms — not overridden).
336
337// Vec<T> — owned, heap-allocated contiguous storage.
338// bool uses `materializing` because bool is not RNativeType (R stores logicals as i32).
339impl_builtin_altrep_family!(
340    Vec<i32>,
341    integer,
342    dataptr,
343    __mx_altrep_reg_builtin_Vec_i32,
344    __MX_ALTREP_REG_ENTRY_builtin_Vec_i32
345);
346impl_builtin_altrep_family!(
347    Vec<f64>,
348    real,
349    dataptr,
350    __mx_altrep_reg_builtin_Vec_f64,
351    __MX_ALTREP_REG_ENTRY_builtin_Vec_f64
352);
353impl_builtin_altrep_family!(
354    Vec<bool>,
355    logical,
356    materializing,
357    __mx_altrep_reg_builtin_Vec_bool,
358    __MX_ALTREP_REG_ENTRY_builtin_Vec_bool
359);
360impl_builtin_altrep_family!(
361    Vec<u8>,
362    raw,
363    dataptr,
364    __mx_altrep_reg_builtin_Vec_u8,
365    __MX_ALTREP_REG_ENTRY_builtin_Vec_u8
366);
367impl_builtin_altrep_family!(
368    Vec<String>,
369    string,
370    dataptr,
371    __mx_altrep_reg_builtin_Vec_String,
372    __MX_ALTREP_REG_ENTRY_builtin_Vec_String
373);
374impl_builtin_altrep_family!(
375    Vec<Option<String>>,
376    string,
377    dataptr,
378    __mx_altrep_reg_builtin_Vec_Option_String,
379    __MX_ALTREP_REG_ENTRY_builtin_Vec_Option_String
380);
381// Cow string vectors — zero-copy from R, ALTREP output without copying back.
382// Serialize: Rf_mkCharLenCE hits R's CHARSXP cache (no string data copy for borrowed).
383// Unserialize: TryFromSexp uses charsxp_to_cow (zero-copy borrow for UTF-8).
384impl_builtin_altrep_family!(
385    Vec<std::borrow::Cow<'static, str>>,
386    string,
387    dataptr,
388    __mx_altrep_reg_builtin_Vec_Cow_str,
389    __MX_ALTREP_REG_ENTRY_builtin_Vec_Cow_str
390);
391impl_builtin_altrep_family!(
392    Vec<Option<std::borrow::Cow<'static, str>>>,
393    string,
394    dataptr,
395    __mx_altrep_reg_builtin_Vec_Option_Cow_str,
396    __MX_ALTREP_REG_ENTRY_builtin_Vec_Option_Cow_str
397);
398impl_builtin_altrep_family!(
399    Vec<crate::Rcomplex>,
400    complex,
401    dataptr,
402    __mx_altrep_reg_builtin_Vec_Rcomplex,
403    __MX_ALTREP_REG_ENTRY_builtin_Vec_Rcomplex
404);
405
406// Range<T> — compute-on-access (no direct pointer); materializes into data2 INTSXP/REALSXP.
407impl_builtin_altrep_family!(
408    std::ops::Range<i32>,
409    integer,
410    materializing,
411    __mx_altrep_reg_builtin_Range_i32,
412    __MX_ALTREP_REG_ENTRY_builtin_Range_i32
413);
414impl_builtin_altrep_family!(
415    std::ops::Range<i64>,
416    integer,
417    materializing,
418    __mx_altrep_reg_builtin_Range_i64,
419    __MX_ALTREP_REG_ENTRY_builtin_Range_i64
420);
421impl_builtin_altrep_family!(
422    std::ops::Range<f64>,
423    real,
424    materializing,
425    __mx_altrep_reg_builtin_Range_f64,
426    __MX_ALTREP_REG_ENTRY_builtin_Range_f64
427);
428// endregion
429
430// region: Box<[T]> implementations
431// Box<[T]> is a fat pointer (Sized) that wraps a DST slice.
432// Unlike Vec<T>, it has no capacity field - just ptr + len (2 words).
433// Useful for fixed-size heap allocations.
434// bool uses `materializing` (same reason as Vec<bool>).
435
436impl_builtin_altrep_family!(
437    Box<[i32]>,
438    integer,
439    dataptr,
440    __mx_altrep_reg_builtin_Box_i32,
441    __MX_ALTREP_REG_ENTRY_builtin_Box_i32
442);
443impl_builtin_altrep_family!(
444    Box<[f64]>,
445    real,
446    dataptr,
447    __mx_altrep_reg_builtin_Box_f64,
448    __MX_ALTREP_REG_ENTRY_builtin_Box_f64
449);
450impl_builtin_altrep_family!(
451    Box<[bool]>,
452    logical,
453    materializing,
454    __mx_altrep_reg_builtin_Box_bool,
455    __MX_ALTREP_REG_ENTRY_builtin_Box_bool
456);
457impl_builtin_altrep_family!(
458    Box<[u8]>,
459    raw,
460    dataptr,
461    __mx_altrep_reg_builtin_Box_u8,
462    __MX_ALTREP_REG_ENTRY_builtin_Box_u8
463);
464impl_builtin_altrep_family!(
465    Box<[String]>,
466    string,
467    dataptr,
468    __mx_altrep_reg_builtin_Box_String,
469    __MX_ALTREP_REG_ENTRY_builtin_Box_String
470);
471impl_builtin_altrep_family!(
472    Box<[crate::Rcomplex]>,
473    complex,
474    dataptr,
475    __mx_altrep_reg_builtin_Box_Rcomplex,
476    __MX_ALTREP_REG_ENTRY_builtin_Box_Rcomplex
477);
478
479// Cow<'static, [T]> — zero-copy borrow from R with copy-on-write dataptr.
480// Borrowed variants expose R's data directly; Owned behaves like Vec.
481impl_builtin_altrep_family!(
482    std::borrow::Cow<'static, [i32]>,
483    integer,
484    dataptr,
485    __mx_altrep_reg_builtin_Cow_i32,
486    __MX_ALTREP_REG_ENTRY_builtin_Cow_i32
487);
488impl_builtin_altrep_family!(
489    std::borrow::Cow<'static, [f64]>,
490    real,
491    dataptr,
492    __mx_altrep_reg_builtin_Cow_f64,
493    __MX_ALTREP_REG_ENTRY_builtin_Cow_f64
494);
495impl_builtin_altrep_family!(
496    std::borrow::Cow<'static, [u8]>,
497    raw,
498    dataptr,
499    __mx_altrep_reg_builtin_Cow_u8,
500    __MX_ALTREP_REG_ENTRY_builtin_Cow_u8
501);
502impl_builtin_altrep_family!(
503    std::borrow::Cow<'static, [crate::Rcomplex]>,
504    complex,
505    dataptr,
506    __mx_altrep_reg_builtin_Cow_Rcomplex,
507    __MX_ALTREP_REG_ENTRY_builtin_Cow_Rcomplex
508);
509
510// endregion
511// region: RegisterAltrep implementations for builtin types
512//
513// These implementations provide ALTREP class registration for Vec<T>, Box<[T]>,
514// and Range<T> types. They allow using these types with ALTREP via wrapper structs.
515//
516// Note: IntoR is NOT implemented here for Vec types because there are already
517// existing IntoR implementations that copy data to R eagerly. To get ALTREP
518// behavior, use wrapper structs:
519//   #[miniextendr(class = "MyVec")]
520//   pub struct MyVecClass(pub Vec<i32>);
521//
522// Each type uses a static OnceLock to cache the ALTREP class handle, which is
523// registered on first use with the current package's name (from ALTREP_PKG_NAME).
524
525use crate::altrep::RegisterAltrep;
526
527/// Helper macro to implement RegisterAltrep for a builtin type.
528macro_rules! impl_register_altrep_builtin {
529    ($ty:ty, $class_name:expr) => {
530        impl RegisterAltrep for $ty {
531            fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
532                use std::sync::OnceLock;
533                static CLASS: OnceLock<crate::sys::altrep::R_altrep_class_t> = OnceLock::new();
534                *CLASS.get_or_init(|| {
535                    // Class name as null-terminated C string
536                    const CLASS_NAME: &[u8] = concat!($class_name, "\0").as_bytes();
537                    let cls = unsafe {
538                        <$ty as crate::altrep_data::InferBase>::make_class(
539                            CLASS_NAME.as_ptr().cast::<std::ffi::c_char>(),
540                            crate::AltrepPkgName::as_ptr(),
541                        )
542                    };
543                    unsafe {
544                        <$ty as crate::altrep_data::InferBase>::install_methods(cls);
545                    }
546                    cls
547                })
548            }
549        }
550    };
551}
552
553// Vec types - RegisterAltrep only (IntoR exists elsewhere, copies data)
554impl_register_altrep_builtin!(Vec<i32>, "Vec_i32");
555impl_register_altrep_builtin!(Vec<f64>, "Vec_f64");
556impl_register_altrep_builtin!(Vec<bool>, "Vec_bool");
557impl_register_altrep_builtin!(Vec<u8>, "Vec_u8");
558impl_register_altrep_builtin!(Vec<String>, "Vec_String");
559impl_register_altrep_builtin!(Vec<Option<String>>, "Vec_Option_String");
560impl_register_altrep_builtin!(Vec<crate::Rcomplex>, "Vec_Rcomplex");
561
562// Range types - RegisterAltrep only
563impl_register_altrep_builtin!(std::ops::Range<i32>, "Range_i32");
564impl_register_altrep_builtin!(std::ops::Range<i64>, "Range_i64");
565impl_register_altrep_builtin!(std::ops::Range<f64>, "Range_f64");
566
567// Box types - RegisterAltrep only
568impl_register_altrep_builtin!(Box<[i32]>, "Box_i32");
569impl_register_altrep_builtin!(Box<[f64]>, "Box_f64");
570impl_register_altrep_builtin!(Box<[bool]>, "Box_bool");
571impl_register_altrep_builtin!(Box<[u8]>, "Box_u8");
572impl_register_altrep_builtin!(Box<[String]>, "Box_String");
573impl_register_altrep_builtin!(Box<[crate::Rcomplex]>, "Box_Rcomplex");
574
575// Cow types - RegisterAltrep for zero-copy borrow from R
576impl_register_altrep_builtin!(std::borrow::Cow<'static, [i32]>, "Cow_i32");
577impl_register_altrep_builtin!(std::borrow::Cow<'static, [f64]>, "Cow_f64");
578impl_register_altrep_builtin!(std::borrow::Cow<'static, [u8]>, "Cow_u8");
579impl_register_altrep_builtin!(std::borrow::Cow<'static, [crate::Rcomplex]>, "Cow_Rcomplex");
580
581// Cow string vector types
582impl_register_altrep_builtin!(Vec<std::borrow::Cow<'static, str>>, "Vec_Cow_str");
583impl_register_altrep_builtin!(
584    Vec<Option<std::borrow::Cow<'static, str>>>,
585    "Vec_Option_Cow_str"
586);
587// endregion