Skip to main content

typed_dataframe

Macro typed_dataframe 

Source
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:

  • i32INTSXP
  • f64REALSXP
  • u8RAWSXP
  • miniextendr_api::RLogicalLGLSXP
  • miniextendr_api::RcomplexCPLXSXP

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) -> usize
  • pub 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
}