Skip to main content

miniextendr_api/altrep_data/
traits.rs

1//! Per-family ALTREP data traits.
2//!
3//! Each ALTREP family has a high-level data trait that users implement:
4//!
5//! | Trait | R Type | Key Method |
6//! |-------|--------|-----------|
7//! | [`AltIntegerData`] | INTSXP | `elt(i) -> i32` |
8//! | [`AltRealData`] | REALSXP | `elt(i) -> f64` |
9//! | [`AltLogicalData`] | LGLSXP | `elt(i) -> Logical` |
10//! | [`AltRawData`] | RAWSXP | `elt(i) -> u8` |
11//! | [`AltComplexData`] | CPLXSXP | `elt(i) -> Rcomplex` |
12//! | [`AltStringData`] | STRSXP | `elt(i) -> Option<&str>` |
13//! | [`AltListData`] | VECSXP | `elt(i) -> SEXP` |
14
15use super::{AltrepLen, Logical, Sortedness, fill_region};
16use crate::ffi::{Rcomplex, SEXP};
17
18// region: Integer ALTREP
19
20/// Trait for types that can back an ALTINTEGER vector.
21///
22/// Implement this to create custom integer ALTREP classes.
23pub trait AltIntegerData: AltrepLen {
24    /// Get the integer element at index `i`.
25    fn elt(&self, i: usize) -> i32;
26
27    /// Optional: return a pointer to contiguous data if available.
28    /// Default returns None (no contiguous backing).
29    fn as_slice(&self) -> Option<&[i32]> {
30        None
31    }
32
33    /// Optional: bulk read into buffer. Returns number of elements read.
34    ///
35    /// Bounds are clamped to the vector length; see `fill_region` for the
36    /// shared safety contract.
37    fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
38        fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
39    }
40
41    /// Optional: sortedness hint. Default is unknown.
42    fn is_sorted(&self) -> Option<Sortedness> {
43        None
44    }
45
46    /// Optional: does this vector contain any NA values?
47    fn no_na(&self) -> Option<bool> {
48        None
49    }
50
51    /// Optional: optimized sum. Default returns None (use R's default).
52    fn sum(&self, _na_rm: bool) -> Option<i64> {
53        None
54    }
55
56    /// Optional: optimized min. Default returns None (use R's default).
57    fn min(&self, _na_rm: bool) -> Option<i32> {
58        None
59    }
60
61    /// Optional: optimized max. Default returns None (use R's default).
62    fn max(&self, _na_rm: bool) -> Option<i32> {
63        None
64    }
65}
66// endregion
67
68// region: Real ALTREP
69
70/// Trait for types that can back an ALTREAL vector.
71pub trait AltRealData: AltrepLen {
72    /// Get the real element at index `i`.
73    fn elt(&self, i: usize) -> f64;
74
75    /// Optional: return a pointer to contiguous data if available.
76    fn as_slice(&self) -> Option<&[f64]> {
77        None
78    }
79
80    /// Optional: bulk read into buffer (clamped to available data).
81    fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
82        fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
83    }
84
85    /// Optional: sortedness hint.
86    fn is_sorted(&self) -> Option<Sortedness> {
87        None
88    }
89
90    /// Optional: does this vector contain any NA values?
91    fn no_na(&self) -> Option<bool> {
92        None
93    }
94
95    /// Optional: optimized sum.
96    fn sum(&self, _na_rm: bool) -> Option<f64> {
97        None
98    }
99
100    /// Optional: optimized min.
101    fn min(&self, _na_rm: bool) -> Option<f64> {
102        None
103    }
104
105    /// Optional: optimized max.
106    fn max(&self, _na_rm: bool) -> Option<f64> {
107        None
108    }
109}
110// endregion
111
112// region: Logical ALTREP
113
114/// Trait for types that can back an ALTLOGICAL vector.
115pub trait AltLogicalData: AltrepLen {
116    /// Get the logical element at index `i`.
117    fn elt(&self, i: usize) -> Logical;
118
119    /// Optional: return a slice if data is contiguous i32 (R's internal format).
120    fn as_r_slice(&self) -> Option<&[i32]> {
121        None
122    }
123
124    /// Optional: bulk read into buffer (clamped to available data).
125    fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
126        fill_region(start, len, self.len(), buf, |idx| self.elt(idx).to_r_int())
127    }
128
129    /// Optional: sortedness hint.
130    fn is_sorted(&self) -> Option<Sortedness> {
131        None
132    }
133
134    /// Optional: does this vector contain any NA values?
135    fn no_na(&self) -> Option<bool> {
136        None
137    }
138
139    /// Optional: optimized sum (count of TRUE values).
140    fn sum(&self, _na_rm: bool) -> Option<i64> {
141        None
142    }
143    // Note: R's ALTREP API does not expose min/max for logical vectors
144}
145// endregion
146
147// region: Raw ALTREP
148
149/// Trait for types that can back an ALTRAW vector.
150pub trait AltRawData: AltrepLen {
151    /// Get the raw byte at index `i`.
152    fn elt(&self, i: usize) -> u8;
153
154    /// Optional: return a slice if data is contiguous.
155    fn as_slice(&self) -> Option<&[u8]> {
156        None
157    }
158
159    /// Optional: bulk read into buffer (clamped to available data).
160    fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
161        fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
162    }
163}
164// endregion
165
166// region: Complex ALTREP
167
168/// Trait for types that can back an ALTCOMPLEX vector.
169pub trait AltComplexData: AltrepLen {
170    /// Get the complex element at index `i`.
171    fn elt(&self, i: usize) -> Rcomplex;
172
173    /// Optional: return a slice if data is contiguous.
174    fn as_slice(&self) -> Option<&[Rcomplex]> {
175        None
176    }
177
178    /// Optional: bulk read into buffer (clamped to available data).
179    fn get_region(&self, start: usize, len: usize, buf: &mut [Rcomplex]) -> usize {
180        fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
181    }
182}
183// endregion
184
185// region: String ALTREP
186
187/// Trait for types that can back an ALTSTRING vector.
188///
189/// Note: `elt` returns a `&str` which will be converted to CHARSXP.
190pub trait AltStringData: AltrepLen {
191    /// Get the string element at index `i`.
192    ///
193    /// Return `None` for NA values.
194    fn elt(&self, i: usize) -> Option<&str>;
195
196    /// Optional: sortedness hint.
197    fn is_sorted(&self) -> Option<Sortedness> {
198        None
199    }
200
201    /// Optional: does this vector contain any NA values?
202    fn no_na(&self) -> Option<bool> {
203        None
204    }
205}
206// endregion
207
208// region: List ALTREP
209
210/// Trait for types that can back an ALTLIST vector.
211///
212/// List elements are arbitrary SEXPs, so this trait works with raw SEXP.
213pub trait AltListData: AltrepLen {
214    /// Get the list element at index `i`.
215    ///
216    /// Returns a SEXP (any R object).
217    fn elt(&self, i: usize) -> SEXP;
218}
219// endregion