miniextendr_api/
cached_class.rs1macro_rules! cached_symbol {
39 ($(#[$meta:meta])* $vis:vis fn $name:ident() = $cstr:expr) => {
40 $(#[$meta])*
41 $vis fn $name() -> $crate::SEXP {
42 static CACHE: ::std::sync::OnceLock<$crate::SEXP> = ::std::sync::OnceLock::new();
43 *CACHE.get_or_init(|| unsafe { $crate::sys::Rf_install($cstr.as_ptr()) })
44 }
45 };
46}
47#[allow(unused_imports)] pub(crate) use cached_symbol;
49
50macro_rules! cached_strsxp {
70 ($(#[$meta:meta])* $vis:vis fn $name:ident() = [$($cstr:expr),+ $(,)?]) => {
71 $(#[$meta])*
72 $vis fn $name() -> $crate::SEXP {
73 static CACHE: ::std::sync::OnceLock<$crate::SEXP> = ::std::sync::OnceLock::new();
74 *CACHE.get_or_init(|| unsafe {
75 use $crate::SexpExt as _;
76 let strings: &[&::std::ffi::CStr] = &[$($cstr),+];
77 let sexp = $crate::sys::Rf_allocVector(
78 $crate::SEXPTYPE::STRSXP,
79 strings.len() as ::std::primitive::isize,
80 );
81 $crate::sys::R_PreserveObject(sexp);
82 for (i, s) in strings.iter().enumerate() {
83 sexp.set_string_elt(
84 i as ::std::primitive::isize,
85 $crate::cached_class::permanent_charsxp(s),
86 );
87 }
88 sexp
89 })
90 }
91 };
92}
93#[allow(unused_imports)] pub(crate) use cached_strsxp;
95
96#[doc(hidden)]
108#[inline]
109pub(crate) fn permanent_charsxp(name: &std::ffi::CStr) -> crate::SEXP {
110 use crate::SexpExt;
111 unsafe { crate::sys::Rf_install(name.as_ptr()) }.printname()
112}
113
114cached_strsxp!(
119 #[cfg(any(feature = "time", feature = "jiff", feature = "arrow"))]
121 pub(crate) fn posixct_class_sexp() = [c"POSIXct", c"POSIXt"]
122);
123
124cached_strsxp!(
125 #[cfg(any(feature = "time", feature = "jiff", feature = "arrow"))]
127 pub(crate) fn date_class_sexp() = [c"Date"]
128);
129
130#[doc = r#" Cached `"data.frame"` class STRSXP."#]
pub(crate) fn data_frame_class_sexp() -> crate::SEXP {
static CACHE: ::std::sync::OnceLock<crate::SEXP> =
::std::sync::OnceLock::new();
*CACHE.get_or_init(||
unsafe {
use crate::SexpExt as _;
let strings: &[&::std::ffi::CStr] = &[c"data.frame"];
let sexp =
crate::sys::Rf_allocVector(crate::SEXPTYPE::STRSXP,
strings.len() as ::std::primitive::isize);
crate::sys::R_PreserveObject(sexp);
for (i, s) in strings.iter().enumerate() {
sexp.set_string_elt(i as ::std::primitive::isize,
crate::cached_class::permanent_charsxp(s));
}
sexp
})
}cached_strsxp!(
131 pub(crate) fn data_frame_class_sexp() = [c"data.frame"]
133);
134
135#[doc =
r#" Cached `"rust_condition_value"` class STRSXP — applied to every tagged"#]
#[doc =
r" SEXP produced by `make_rust_condition_value` to identify panic-transport"]
#[doc = r" values to the generated R wrappers."]
pub(crate) fn rust_condition_class_sexp() -> crate::SEXP {
static CACHE: ::std::sync::OnceLock<crate::SEXP> =
::std::sync::OnceLock::new();
*CACHE.get_or_init(||
unsafe {
use crate::SexpExt as _;
let strings: &[&::std::ffi::CStr] =
&[c"rust_condition_value"];
let sexp =
crate::sys::Rf_allocVector(crate::SEXPTYPE::STRSXP,
strings.len() as ::std::primitive::isize);
crate::sys::R_PreserveObject(sexp);
for (i, s) in strings.iter().enumerate() {
sexp.set_string_elt(i as ::std::primitive::isize,
crate::cached_class::permanent_charsxp(s));
}
sexp
})
}cached_strsxp!(
136 pub(crate) fn rust_condition_class_sexp() = [c"rust_condition_value"]
140);
141
142#[doc =
r#" Cached `c("error", "kind", "class", "call", "data")` names STRSXP for"#]
#[doc = r" condition values."]
#[doc = r""]
#[doc =
r" Used by `make_rust_condition_value` which writes a 5-element list: the"]
#[doc =
r" error message, kind, optional user-supplied custom class, optional R"]
#[doc =
r" call, and an optional named-list `data` payload (`NULL` when absent)."]
pub(crate) fn condition_names_sexp() -> crate::SEXP {
static CACHE: ::std::sync::OnceLock<crate::SEXP> =
::std::sync::OnceLock::new();
*CACHE.get_or_init(||
unsafe {
use crate::SexpExt as _;
let strings: &[&::std::ffi::CStr] =
&[c"error", c"kind", c"class", c"call", c"data"];
let sexp =
crate::sys::Rf_allocVector(crate::SEXPTYPE::STRSXP,
strings.len() as ::std::primitive::isize);
crate::sys::R_PreserveObject(sexp);
for (i, s) in strings.iter().enumerate() {
sexp.set_string_elt(i as ::std::primitive::isize,
crate::cached_class::permanent_charsxp(s));
}
sexp
})
}cached_strsxp!(
143 pub(crate) fn condition_names_sexp() = [c"error", c"kind", c"class", c"call", c"data"]
150);
151
152cached_strsxp!(
157 #[cfg(any(feature = "time", feature = "jiff"))]
159 fn utc_tzone_sexp() = [c"UTC"]
160);
161
162cached_symbol!(
167 #[cfg(any(feature = "time", feature = "jiff", feature = "arrow"))]
169 pub(crate) fn tzone_symbol() = c"tzone"
170);
171
172#[doc =
r" Cached `__rust_condition__` symbol — the marker attribute on tagged"]
#[doc =
r" panic-transport SEXPs. Wrapper code asserts this is `TRUE` in addition"]
#[doc =
r" to the class check before re-raising via `.miniextendr_raise_condition`."]
pub(crate) fn rust_condition_attr_symbol() -> crate::SEXP {
static CACHE: ::std::sync::OnceLock<crate::SEXP> =
::std::sync::OnceLock::new();
*CACHE.get_or_init(||
unsafe {
crate::sys::Rf_install(c"__rust_condition__".as_ptr())
})
}cached_symbol!(
173 pub(crate) fn rust_condition_attr_symbol() = c"__rust_condition__"
177);
178
179#[doc =
r" Cached `miniextendr_written` symbol: the attribute a string ALTREP's"]
#[doc = r" data2 cache carries once R has stored a value into it."]
pub(crate) fn altstring_written_symbol() -> crate::SEXP {
static CACHE: ::std::sync::OnceLock<crate::SEXP> =
::std::sync::OnceLock::new();
*CACHE.get_or_init(||
unsafe {
crate::sys::Rf_install(c"miniextendr_written".as_ptr())
})
}cached_symbol!(
180 pub(crate) fn altstring_written_symbol() = c"miniextendr_written"
183);
184
185cached_symbol!(
186 #[cfg(feature = "raw_conversions")]
188 pub(crate) fn mx_raw_type_symbol() = c"mx_raw_type"
189);
190
191cached_symbol!(
192 #[cfg(feature = "vctrs")]
194 pub(crate) fn ptype_symbol() = c"ptype"
195);
196
197cached_symbol!(
198 #[cfg(feature = "vctrs")]
200 pub(crate) fn size_symbol() = c"size"
201);
202
203#[cfg(any(feature = "time", feature = "jiff"))]
215pub fn set_posixct_utc(sexp: crate::SEXP) {
216 use crate::SexpExt as _;
217 sexp.set_class(posixct_class_sexp());
218 sexp.set_attr(tzone_symbol(), utc_tzone_sexp());
219}
220
221#[cfg(feature = "jiff")]
230pub fn set_posixct_tz(sexp: crate::SEXP, iana: &str) {
231 use crate::SexpExt as _;
232 sexp.set_class(posixct_class_sexp());
233 unsafe {
235 let tzone_charsxp = crate::SEXP::charsxp(iana);
236 let tzone_sexp = crate::sys::Rf_allocVector(crate::SEXPTYPE::STRSXP, 1);
237 let _guard = crate::OwnedProtect::new(tzone_sexp);
238 tzone_sexp.set_string_elt(0, tzone_charsxp);
239 sexp.set_attr(tzone_symbol(), tzone_sexp);
240 }
241}
242
243