miniextendr_api/altrep_ext.rs
1//! Extension trait for SEXP providing ALTREP-specific accessors.
2//!
3//! Using methods on SEXP (via `&self`) instead of free functions avoids
4//! `clippy::not_unsafe_ptr_arg_deref` in ALTREP trait implementations,
5//! mirroring the pattern established by [`SexpExt`](crate::ffi::SexpExt).
6
7use crate::externalptr::{ExternalPtr, TypedExternal};
8use crate::ffi::SEXP;
9
10/// ALTREP-specific extension methods for SEXP.
11///
12/// These methods wrap the free functions in `externalptr::altrep_helpers`
13/// and `ffi::altrep`, converting `func(x)` calls to `x.method()` calls.
14/// This avoids the `clippy::not_unsafe_ptr_arg_deref` lint in ALTREP trait
15/// method implementations that receive SEXP as a parameter.
16pub trait AltrepSexpExt {
17 /// Extract the ALTREP data1 slot as a typed `ExternalPtr<T>`.
18 ///
19 /// # Safety
20 ///
21 /// - `self` must be a valid ALTREP SEXP
22 /// - Must be called from the R main thread
23 unsafe fn altrep_data1<T: TypedExternal>(&self) -> Option<ExternalPtr<T>>;
24
25 /// Get a mutable reference to data in the ALTREP data1 slot.
26 ///
27 /// # Safety
28 ///
29 /// - `self` must be a valid ALTREP SEXP
30 /// - Must be called from the R main thread
31 /// - The caller must ensure no other references to the data exist
32 unsafe fn altrep_data1_mut_ref<T: TypedExternal>(&self) -> Option<&'static mut T>;
33
34 /// Get the ALTREP data2 slot.
35 ///
36 /// # Safety
37 ///
38 /// - `self` must be a valid ALTREP SEXP
39 /// - Must be called from the R main thread
40 unsafe fn altrep_data2(&self) -> SEXP;
41
42 /// Set the ALTREP data2 slot.
43 ///
44 /// # Safety
45 ///
46 /// - `self` must be a valid ALTREP SEXP
47 /// - Must be called from the R main thread
48 unsafe fn set_altrep_data2(&self, data2: SEXP);
49}
50
51impl AltrepSexpExt for SEXP {
52 #[inline]
53 unsafe fn altrep_data1<T: TypedExternal>(&self) -> Option<ExternalPtr<T>> {
54 unsafe { crate::altrep_data1_as::<T>(*self) }
55 }
56
57 #[inline]
58 unsafe fn altrep_data1_mut_ref<T: TypedExternal>(&self) -> Option<&'static mut T> {
59 unsafe { crate::altrep_data1_mut::<T>(*self) }
60 }
61
62 #[inline]
63 unsafe fn altrep_data2(&self) -> SEXP {
64 unsafe { crate::ffi::R_altrep_data2(*self) }
65 }
66
67 #[inline]
68 unsafe fn set_altrep_data2(&self, data2: SEXP) {
69 unsafe { crate::ffi::R_set_altrep_data2(*self, data2) }
70 }
71}