Skip to main content

miniextendr_api/
altrep_impl.rs

1//! ALTREP implementation utilities.
2//!
3//! This module provides helper functions used by the declarative macros
4//! generated for ALTREP classes.  The proc-macro derives (`#[derive(AltrepInteger)]`
5//! etc.) lower to invocations of `impl_alt*_from_data!` macros which expand
6//! to code that references items in this module via `$crate::altrep_impl::*`
7//! paths.
8//!
9//! Use `crate::altrep_data1_as` (re-exported from externalptr) to extract
10//! data from an ALTREP's data1 slot.
11//!
12//! ## Layout
13//!
14//! - [`macros`] — `#[macro_export]` declarative macros (`impl_alt*_from_data!`
15//!   and their `__impl_*` helpers).
16//! - [`builtins`] — crate-private meta-macro + invocations for `Vec<T>` /
17//!   `Box<[T]>` / `Cow<T>` / `Range<T>` ALTREP families.
18//! - [`arrays`] — const-generic `[T; N]` ALTREP impls.
19//! - [`static_slices`] — hand-written `&'static [T]` ALTREP impls.
20
21// region: Checked string-to-CHARSXP helper
22
23/// Create a CHARSXP from a Rust string, with checked length conversion.
24///
25/// # Safety
26///
27/// Must be called from R's main thread.
28///
29/// # Panics
30///
31/// Panics if `s.len() > i32::MAX`.
32#[inline]
33pub unsafe fn checked_mkchar(s: &str) -> crate::SEXP {
34    let _len = i32::try_from(s.len()).unwrap_or_else(|_| {
35        panic!(
36            "string length {} exceeds i32::MAX for Rf_mkCharLenCE",
37            s.len()
38        )
39    });
40    crate::SEXP::charsxp(s)
41}
42// endregion
43
44// region: Centralized ALTREP buffer access helper
45
46/// Create a mutable slice from an ALTREP `get_region` output buffer pointer.
47///
48/// Called by the bridge trampolines (`altrep_bridge.rs`) to convert the raw
49/// `*mut T` buffer from R's ALTREP dispatch into a `&mut [T]` before passing
50/// it to the trait methods.
51///
52/// # Safety
53///
54/// - `buf` must be a valid, aligned, writable pointer to at least `len` elements of `T`.
55/// - The caller must ensure no aliasing references to the same memory exist.
56/// - This is guaranteed when called from R's ALTREP `Get_region` dispatch, which
57///   provides a freshly allocated buffer.
58#[inline]
59pub unsafe fn altrep_region_buf<T>(buf: *mut T, len: usize) -> &'static mut [T] {
60    unsafe { std::slice::from_raw_parts_mut(buf, len) }
61}
62// endregion
63
64// `macros` is declared first so its `#[macro_export]` items are textually
65// in-scope before the `builtins`/`arrays`/`static_slices` modules that invoke
66// them via `$crate::__impl_alt_*` paths.
67pub mod macros;
68
69pub mod arrays;
70pub mod builtins;
71pub mod static_slices;