pub trait AltIntegerData: AltrepLen {
// Required method
fn elt(&self, i: usize) -> i32;
// Provided methods
fn as_slice(&self) -> Option<&[i32]> { ... }
fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize { ... }
fn is_sorted(&self) -> Option<Sortedness> { ... }
fn no_na(&self) -> Option<bool> { ... }
fn sum(&self, _na_rm: bool) -> Option<i64> { ... }
fn min(&self, _na_rm: bool) -> Option<i32> { ... }
fn max(&self, _na_rm: bool) -> Option<i32> { ... }
}Expand description
Trait for types that can back an ALTINTEGER vector.
Implement this to create custom integer ALTREP classes.
Required Methods§
Provided Methods§
Sourcefn as_slice(&self) -> Option<&[i32]>
fn as_slice(&self) -> Option<&[i32]>
Optional: return a pointer to contiguous data if available. Default returns None (no contiguous backing).
Sourcefn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize
fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize
Optional: bulk read into buffer. Returns number of elements read.
Bounds are clamped to the vector length; see fill_region for the
shared safety contract.
R calls this when scanning the vector in bulk (sum(), anyNA(),
duplicated(), printing, …), usually in blocks of up to 512
elements via ITERATE_BY_REGION, but occasionally with len equal
to the full vector length — never assume a block size. Calls are
synchronous pulls on the R main thread; a class cannot schedule or
prefetch them.
The default fills element-by-element from elt, which
already costs only one FFI dispatch per block. Override it when the
block has structure a per-element accessor would recompute (hoistable
per-block invariants, contiguous sub-ranges, chunked decoding).
§Contract
Fill at most len.min(buf.len()).min(self.len() - start) elements
starting at start, and return the count actually written. A start
at or past the end returns 0.
§Examples
A lazy arithmetic sequence with a bulk fill that hoists the block base out of the loop:
use miniextendr_api::altrep_data::{AltIntegerData, AltrepLen};
/// Lazy arithmetic sequence: element i is `start + i * step`.
struct LazySeq { start: i32, step: i32, len: usize }
impl AltrepLen for LazySeq {
fn len(&self) -> usize { self.len }
}
impl AltIntegerData for LazySeq {
fn elt(&self, i: usize) -> i32 {
self.start + (i as i32) * self.step
}
/// Bulk fill: clamp once, hoist the block base out of the loop,
/// then write `buf` sequentially (cache-friendly, no per-element
/// bounds or dispatch overhead).
fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
let n = len.min(buf.len()).min(self.len.saturating_sub(start));
let base = self.start + (start as i32) * self.step;
for (k, slot) in buf[..n].iter_mut().enumerate() {
*slot = base + (k as i32) * self.step;
}
n
}
}
let seq = LazySeq { start: 10, step: 2, len: 100 };
let mut buf = [0i32; 8];
// Interior block: fully filled.
assert_eq!(seq.get_region(5, 8, &mut buf), 8);
assert_eq!(buf, [20, 22, 24, 26, 28, 30, 32, 34]);
// Tail block: clamped to the vector length.
assert_eq!(seq.get_region(96, 8, &mut buf), 4);
assert_eq!(&buf[..4], &[202, 204, 206, 208]);
// Past the end: nothing written.
assert_eq!(seq.get_region(100, 8, &mut buf), 0);Sourcefn is_sorted(&self) -> Option<Sortedness>
fn is_sorted(&self) -> Option<Sortedness>
Optional: sortedness hint. Default is unknown.
Sourcefn sum(&self, _na_rm: bool) -> Option<i64>
fn sum(&self, _na_rm: bool) -> Option<i64>
Optional: optimized sum. Default returns None (use R’s default).
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".