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