#[derive(TryFromSexp)]
{
// Attributes available to this derive:
#[try_from_sexp]
}
Expand description
Derive TryFromSexp for a single-field newtype: forward the R → Rust
conversion to the inner type.
Generates a scalar TryFromSexp impl that delegates to the inner type (so the
newtype inherits its exact SEXPTYPE checks, NA policy, and error text), plus a
TryFromSexpElement marker impl. The marker lets miniextendr-api’s container
blankets light up Vec<T> / Option<T> / Vec<Option<T>> automatically,
each one where the inner type’s container converts.
Don’t use it on a type that also gets try_from_sexp_via_str_parse!: both
implement TryFromSexpElement.
§Usage
use uuid::Uuid;
#[derive(TryFromSexp)] // R -> Rust only
struct Pattern(regex::Regex);
#[derive(TryFromSexp, IntoR)] // round-trip; Vec/Option containers work too
struct UserId(Uuid);Direction is chosen by which derive you list — derive only TryFromSexp for
inner types that read from R but cannot be written back (e.g. regex::Regex).
§Refusing values: #[try_from_sexp(validate = path)]
The containers read the inner type and wrap it; they never run the
newtype’s own try_from_sexp. To refuse a value the inner type accepts,
name a check, fn(SEXP) -> Result<(), E> with E: Into<SexpError>. It
becomes TryFromSexpElement::check_sexp, which runs on the R value before
it is read, in every shape: the scalar, on any input but NULL for
Option<T>, and for Vec<T> and Vec<Option<T>> once on the whole vector
of an atomic inner type, or on each element (but NULL) of a list when the
inner type is List (a list of R objects, each with its own class).
use miniextendr_api::condition::RError;
use miniextendr_api::{SEXP, SexpExt, TryFromSexp};
fn plain_number(x: SEXP) -> Result<(), RError> {
if x.inherits_class(c"difftime") {
return Err(RError::new("give the duration as a plain number").class("pkg_unit_error"));
}
Ok(())
}
#[derive(TryFromSexp)]
#[try_from_sexp(validate = plain_number)]
struct Duration(f64);An RError refusal (or one of any RConditionData type) keeps its classes
and fields on the argument error, before the crate’s
conversion_error_class, with e$param and the message
'<p>' must be <expected>: <message>. With validate, the newtype’s
scalar error is SexpError, so the inner type’s error must convert into it,
as every built-in conversion error and every RConditionData type does.
validate is the only key, and the attribute goes on the struct.