typed_dataframe!() { /* proc-macro */ }Expand description
Define a compile-time-validated wrapper for an R data.frame input.
typed_dataframe! mirrors typed_list! for the data.frame shape:
declare the columns once, get a struct that implements TryFromSexp
(validating both the data.frame class and per-column SEXPTYPE) plus
per-column borrowed accessors that return &[T].
§Syntax
typed_dataframe! {
/// The shape we accept for the Theoph PK dataset.
pub TheophDf {
subject: i32,
weight: f64,
dose: f64,
flag: Option<i32>, // optional column
}
}For strict mode (reject any column not declared):
typed_dataframe! {
@exact;
pub Strict { x: i32 }
}§Supported element types
v1 supports column element types that implement
miniextendr_api::RNativeType:
i32—INTSXPf64—REALSXPu8—RAWSXPminiextendr_api::RLogical—LGLSXPminiextendr_api::Rcomplex—CPLXSXP
String/&str column types are not yet supported (character vectors
don’t expose a contiguous slice). bool is also not yet supported as
a direct field type — use RLogical and convert per-element, or
follow the open follow-up issues from PR #698.
§Generated API
For each name: T column the macro emits:
pub fn name(&self) -> &[T](required)pub fn name(&self) -> Option<&[T]>(optional,Option<T>)
Plus housekeeping:
pub fn nrow(&self) -> usizepub fn ncol(&self) -> usize(count of declared columns)pub fn as_sexp(&self) -> SEXP
All borrowed accessors are bound to &self; the SEXP is protected
by the surrounding #[miniextendr] call wrapper while the struct is
alive.
§Error reporting
TryFromSexp::try_from_sexp batches every per-column error into a
single SexpError::InvalidValue, so the R user sees one diagnostic
covering all missing or wrong-typed columns rather than a sequence of
stop-on-first-failure messages.
§Example
use miniextendr_api::{miniextendr, typed_dataframe};
typed_dataframe! {
pub TheophDf {
subject: i32,
weight: f64,
dose: f64,
}
}
#[miniextendr]
pub fn theoph_nrow(df: TheophDf) -> i32 {
// df.subject() -> &[i32], df.weight() -> &[f64]
// Lengths are guaranteed equal across columns (data.frame invariant).
df.nrow() as i32
}