Skip to main content

miniextendr_api/
altrep_traits.rs

1//! Safe, idiomatic ALTREP trait hierarchy mirroring R's method tables.
2//!
3//! ## Design: Required vs Optional Methods
4//!
5//! Each ALTREP type family has:
6//! - **Required methods** (no defaults) - compiler enforces implementation
7//! - **Optional methods** with `HAS_*` const gating - defaults to `false` (not installed)
8//!
9//! When `HAS_*` is false, the method is NOT installed with R, so R uses its own default behavior.
10//!
11//! ## Required Methods by Type
12//!
13//! | Type | Required Methods |
14//! |------|------------------|
15//! | All | `length` |
16//! | ALTSTRING | `length` + `elt` |
17//! | ALTLIST | `length` + `elt` |
18//! | Numeric types | `length` + (`elt` OR `dataptr` via HAS_*) |
19//!
20//! ## Guard mode ([`Altrep::GUARD`])
21//!
22//! Native reads and inspection use `const GUARD: AltrepGuard` on the type.
23//! Callbacks returning SEXP, Dataptr and string/list setters always use
24//! `RUnwind`: their framework bridges can allocate R objects. For the remaining
25//! callbacks, the three modes are resolved at compile time:
26//!
27//! | Mode | What it wraps | Use when |
28//! |---|---|---|
29//! | [`AltrepGuard::Unsafe`] | nothing | callback is trivial, allocation-free, and cannot panic |
30//! | [`AltrepGuard::RustUnwind`] | [`catch_unwind`](std::panic::catch_unwind) | pure-Rust callback that may panic but never enters R API code |
31//! | [`AltrepGuard::RUnwind`] *(default)* | `R_UnwindProtect` (R's C API) | callback calls into R (e.g. `Rf_mkCharLenCE`, `Rf_allocVector`) and may longjmp |
32//!
33//! The derive surface exposes the same three modes as `#[altrep(unsafe)]` /
34//! `#[altrep(rust_unwind)]` / `#[altrep(r_unwind)]`; bridging through these
35//! modes is handled by [`crate::altrep_bridge`].
36
37use crate::{R_xlen_t, Rcomplex, SEXP, SEXPTYPE};
38use core::ffi::c_void;
39
40// region: ALTREP GUARD MODE
41
42/// Controls the panic/error guard used around ALTREP trampoline callbacks.
43///
44/// Each mode trades off safety vs performance:
45///
46/// - [`Unsafe`](AltrepGuard::Unsafe): No protection. If the callback panics,
47///   behavior is undefined (unwinding through C frames). Use only for trivial
48///   callbacks that cannot panic.
49///
50/// - [`RustUnwind`](AltrepGuard::RustUnwind): Wraps in `catch_unwind`, converting
51///   Rust panics to R errors. Suitable for pure-Rust callbacks.
52///
53/// - [`RUnwind`](AltrepGuard::RUnwind): Wraps in `R_UnwindProtect`, catching both
54///   Rust panics and R `longjmp` errors. This is the default. Use when ALTREP callbacks invoke R API
55///   functions that might error (e.g., `Rf_allocVector`, `Rf_eval`).
56///
57/// The guard is selected via the `const GUARD` associated constant on the [`Altrep`]
58/// trait. Since it is a const, the compiler eliminates dead branches at
59/// monomorphization time — zero runtime overhead for the chosen mode.
60#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for AltrepGuard { }
#[automatically_derived]
impl ::core::clone::Clone for AltrepGuard {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AltrepGuard { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for AltrepGuard { }
#[automatically_derived]
impl ::core::cmp::PartialEq for AltrepGuard {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for AltrepGuard { }Eq, #[automatically_derived]
impl ::core::fmt::Debug for AltrepGuard {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                AltrepGuard::Unsafe => "Unsafe",
                AltrepGuard::RustUnwind => "RustUnwind",
                AltrepGuard::RUnwind => "RUnwind",
            })
    }
}Debug)]
61pub enum AltrepGuard {
62    /// No protection. Fastest, but if the callback panics, behavior is undefined.
63    Unsafe,
64    /// `catch_unwind` — catches Rust panics, converts to R errors.
65    RustUnwind,
66    /// `with_r_unwind_protect` — catches both Rust panics and R longjmps.
67    /// Use when ALTREP callbacks invoke R API functions that might error.
68    RUnwind,
69}
70// endregion
71
72// region: ALTREP BASE
73
74/// Base ALTREP methods.
75///
76/// `length` is REQUIRED (no default). All other methods are optional with HAS_* gating.
77pub trait Altrep {
78    /// The guard mode for native reads and inspection on this type.
79    ///
80    /// Defaults to [`AltrepGuard::RUnwind`] which catches both Rust panics and
81    /// R longjmps via `R_UnwindProtect`. This is safe for all callbacks, including
82    /// those that call R API functions (e.g., `Rf_mkCharLenCE`, `Rf_ScalarReal`,
83    /// `into_sexp` in serialization).
84    ///
85    /// Override to [`AltrepGuard::RustUnwind`] if your callbacks never call R APIs
86    /// that can longjmp, or [`AltrepGuard::Unsafe`] for trivial callbacks that
87    /// cannot panic. SEXP-returning callbacks, Dataptr and string/list setters
88    /// always retain RUnwind protection, including when this selects another mode.
89    const GUARD: AltrepGuard = AltrepGuard::RUnwind;
90
91    // --- REQUIRED ---
92    /// Returns the length of the ALTREP vector.
93    /// This is REQUIRED - R cannot determine vector length without it.
94    fn length(x: SEXP) -> R_xlen_t;
95
96    // --- OPTIONAL: Serialization ---
97    /// Set to `true` to register [`serialized_state`](Self::serialized_state).
98    const HAS_SERIALIZED_STATE: bool = false;
99    /// Return serialization state.
100    fn serialized_state(_x: SEXP) -> SEXP {
101        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_SERIALIZED_STATE = false")));
}unreachable!("HAS_SERIALIZED_STATE = false")
102    }
103
104    /// Set to `true` to register [`unserialize`](Self::unserialize).
105    const HAS_UNSERIALIZE: bool = false;
106    /// Reconstruct ALTREP from serialized state.
107    fn unserialize(_class: SEXP, _state: SEXP) -> SEXP {
108        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_UNSERIALIZE = false")));
}unreachable!("HAS_UNSERIALIZE = false")
109    }
110
111    /// Set to `true` to register [`unserialize_ex`](Self::unserialize_ex).
112    const HAS_UNSERIALIZE_EX: bool = false;
113    /// Extended unserialization with attributes.
114    fn unserialize_ex(_class: SEXP, _state: SEXP, _attr: SEXP, _objf: i32, _levs: i32) -> SEXP {
115        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_UNSERIALIZE_EX = false")));
}unreachable!("HAS_UNSERIALIZE_EX = false")
116    }
117
118    // --- OPTIONAL: Duplication ---
119    /// Set to `true` to register [`duplicate`](Self::duplicate).
120    const HAS_DUPLICATE: bool = false;
121    /// Duplicate the ALTREP object.
122    fn duplicate(_x: SEXP, _deep: bool) -> SEXP {
123        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_DUPLICATE = false")));
}unreachable!("HAS_DUPLICATE = false")
124    }
125
126    /// Set to `true` to register [`duplicate_ex`](Self::duplicate_ex).
127    const HAS_DUPLICATE_EX: bool = false;
128    /// Extended duplication.
129    fn duplicate_ex(_x: SEXP, _deep: bool) -> SEXP {
130        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_DUPLICATE_EX = false")));
}unreachable!("HAS_DUPLICATE_EX = false")
131    }
132
133    // --- OPTIONAL: Coercion ---
134    /// Set to `true` to register [`coerce`](Self::coerce).
135    const HAS_COERCE: bool = false;
136    /// Coerce to another type.
137    fn coerce(_x: SEXP, _to_type: SEXPTYPE) -> SEXP {
138        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_COERCE = false")));
}unreachable!("HAS_COERCE = false")
139    }
140
141    // --- OPTIONAL: Inspection ---
142    /// Set to `true` to register [`inspect`](Self::inspect).
143    const HAS_INSPECT: bool = false;
144    /// Custom inspection for `.Internal(inspect())`.
145    fn inspect(
146        _x: SEXP,
147        _pre: i32,
148        _deep: i32,
149        _pvec: i32,
150        _inspect_subtree: Option<unsafe extern "C-unwind" fn(SEXP, i32, i32, i32)>,
151    ) -> bool {
152        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_INSPECT = false")));
}unreachable!("HAS_INSPECT = false")
153    }
154}
155// endregion
156
157// region: ALTVEC - Vector-level methods (extends Altrep)
158
159/// Vector-level methods.
160///
161/// All methods are optional with HAS_* gating.
162pub trait AltVec: Altrep {
163    /// Set to `true` to register [`dataptr`](Self::dataptr).
164    const HAS_DATAPTR: bool = false;
165    /// Get raw data pointer.
166    fn dataptr(_x: SEXP, _writable: bool) -> *mut c_void {
167        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_DATAPTR = false")));
}unreachable!("HAS_DATAPTR = false")
168    }
169
170    /// Set to `true` to register [`dataptr_or_null`](Self::dataptr_or_null).
171    const HAS_DATAPTR_OR_NULL: bool = false;
172    /// Get data pointer without forcing materialization.
173    fn dataptr_or_null(_x: SEXP) -> *const c_void {
174        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_DATAPTR_OR_NULL = false")));
}unreachable!("HAS_DATAPTR_OR_NULL = false")
175    }
176
177    /// Set to `true` to register [`extract_subset`](Self::extract_subset).
178    const HAS_EXTRACT_SUBSET: bool = false;
179    /// Optimized subsetting.
180    fn extract_subset(_x: SEXP, _indx: SEXP, _call: SEXP) -> SEXP {
181        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_EXTRACT_SUBSET = false")));
}unreachable!("HAS_EXTRACT_SUBSET = false")
182    }
183}
184// endregion
185
186// region: ALTINTEGER - Integer vector methods
187
188/// Integer vector methods.
189///
190/// For ALTINTEGER, you must provide EITHER:
191/// - `HAS_ELT = true` with `elt()` implementation, OR
192/// - `HAS_DATAPTR = true` with `dataptr()` implementation
193///
194/// If neither is provided, R will error at runtime when accessing elements.
195pub trait AltInteger: AltVec {
196    /// Set to `true` to register [`elt`](Self::elt).
197    const HAS_ELT: bool = false;
198    /// Get element at index.
199    fn elt(_x: SEXP, _i: R_xlen_t) -> i32 {
200        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_ELT = false")));
}unreachable!("HAS_ELT = false")
201    }
202
203    /// Set to `true` to register [`get_region`](Self::get_region).
204    const HAS_GET_REGION: bool = false;
205    /// Bulk read elements into buffer.
206    fn get_region(_x: SEXP, _i: R_xlen_t, _n: R_xlen_t, _buf: &mut [i32]) -> R_xlen_t {
207        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_GET_REGION = false")));
}unreachable!("HAS_GET_REGION = false")
208    }
209
210    /// Set to `true` to register [`is_sorted`](Self::is_sorted).
211    const HAS_IS_SORTED: bool = false;
212    /// Sortedness hint.
213    fn is_sorted(_x: SEXP) -> i32 {
214        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_IS_SORTED = false")));
}unreachable!("HAS_IS_SORTED = false")
215    }
216
217    /// Set to `true` to register [`no_na`](Self::no_na).
218    const HAS_NO_NA: bool = false;
219    /// NA-free hint.
220    fn no_na(_x: SEXP) -> i32 {
221        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_NO_NA = false")));
}unreachable!("HAS_NO_NA = false")
222    }
223
224    /// Set to `true` to register [`sum`](Self::sum).
225    const HAS_SUM: bool = false;
226    /// Optimized sum.
227    fn sum(_x: SEXP, _narm: bool) -> SEXP {
228        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_SUM = false")));
}unreachable!("HAS_SUM = false")
229    }
230
231    /// Set to `true` to register [`min`](Self::min).
232    const HAS_MIN: bool = false;
233    /// Optimized min.
234    fn min(_x: SEXP, _narm: bool) -> SEXP {
235        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_MIN = false")));
}unreachable!("HAS_MIN = false")
236    }
237
238    /// Set to `true` to register [`max`](Self::max).
239    const HAS_MAX: bool = false;
240    /// Optimized max.
241    fn max(_x: SEXP, _narm: bool) -> SEXP {
242        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_MAX = false")));
}unreachable!("HAS_MAX = false")
243    }
244}
245// endregion
246
247// region: ALTREAL - Real (double) vector methods
248
249/// Real vector methods.
250pub trait AltReal: AltVec {
251    /// Set to `true` to register [`elt`](Self::elt).
252    const HAS_ELT: bool = false;
253    /// Get element at index.
254    fn elt(_x: SEXP, _i: R_xlen_t) -> f64 {
255        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_ELT = false")));
}unreachable!("HAS_ELT = false")
256    }
257
258    /// Set to `true` to register [`get_region`](Self::get_region).
259    const HAS_GET_REGION: bool = false;
260    /// Bulk read elements into buffer.
261    fn get_region(_x: SEXP, _i: R_xlen_t, _n: R_xlen_t, _buf: &mut [f64]) -> R_xlen_t {
262        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_GET_REGION = false")));
}unreachable!("HAS_GET_REGION = false")
263    }
264
265    /// Set to `true` to register [`is_sorted`](Self::is_sorted).
266    const HAS_IS_SORTED: bool = false;
267    /// Sortedness hint.
268    fn is_sorted(_x: SEXP) -> i32 {
269        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_IS_SORTED = false")));
}unreachable!("HAS_IS_SORTED = false")
270    }
271
272    /// Set to `true` to register [`no_na`](Self::no_na).
273    const HAS_NO_NA: bool = false;
274    /// NA-free hint.
275    fn no_na(_x: SEXP) -> i32 {
276        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_NO_NA = false")));
}unreachable!("HAS_NO_NA = false")
277    }
278
279    /// Set to `true` to register [`sum`](Self::sum).
280    const HAS_SUM: bool = false;
281    /// Optimized sum.
282    fn sum(_x: SEXP, _narm: bool) -> SEXP {
283        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_SUM = false")));
}unreachable!("HAS_SUM = false")
284    }
285
286    /// Set to `true` to register [`min`](Self::min).
287    const HAS_MIN: bool = false;
288    /// Optimized min.
289    fn min(_x: SEXP, _narm: bool) -> SEXP {
290        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_MIN = false")));
}unreachable!("HAS_MIN = false")
291    }
292
293    /// Set to `true` to register [`max`](Self::max).
294    const HAS_MAX: bool = false;
295    /// Optimized max.
296    fn max(_x: SEXP, _narm: bool) -> SEXP {
297        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_MAX = false")));
}unreachable!("HAS_MAX = false")
298    }
299}
300// endregion
301
302// region: ALTLOGICAL - Logical vector methods
303
304/// Logical vector methods.
305pub trait AltLogical: AltVec {
306    /// Set to `true` to register [`elt`](Self::elt).
307    const HAS_ELT: bool = false;
308    /// Returns i32: 0=FALSE, 1=TRUE, NA_LOGICAL=NA
309    fn elt(_x: SEXP, _i: R_xlen_t) -> i32 {
310        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_ELT = false")));
}unreachable!("HAS_ELT = false")
311    }
312
313    /// Set to `true` to register [`get_region`](Self::get_region).
314    const HAS_GET_REGION: bool = false;
315    /// Bulk read elements into buffer.
316    fn get_region(_x: SEXP, _i: R_xlen_t, _n: R_xlen_t, _buf: &mut [i32]) -> R_xlen_t {
317        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_GET_REGION = false")));
}unreachable!("HAS_GET_REGION = false")
318    }
319
320    /// Set to `true` to register [`is_sorted`](Self::is_sorted).
321    const HAS_IS_SORTED: bool = false;
322    /// Sortedness hint.
323    fn is_sorted(_x: SEXP) -> i32 {
324        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_IS_SORTED = false")));
}unreachable!("HAS_IS_SORTED = false")
325    }
326
327    /// Set to `true` to register [`no_na`](Self::no_na).
328    const HAS_NO_NA: bool = false;
329    /// NA-free hint.
330    fn no_na(_x: SEXP) -> i32 {
331        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_NO_NA = false")));
}unreachable!("HAS_NO_NA = false")
332    }
333
334    /// Set to `true` to register [`sum`](Self::sum).
335    const HAS_SUM: bool = false;
336    /// Sum for logical = count of TRUE values.
337    fn sum(_x: SEXP, _narm: bool) -> SEXP {
338        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_SUM = false")));
}unreachable!("HAS_SUM = false")
339    }
340    // Note: R's ALTREP API does not expose min/max for logical vectors
341}
342// endregion
343
344// region: ALTRAW - Raw (byte) vector methods
345
346/// Raw vector methods.
347pub trait AltRaw: AltVec {
348    /// Set to `true` to register [`elt`](Self::elt).
349    const HAS_ELT: bool = false;
350    /// Get element at index.
351    fn elt(_x: SEXP, _i: R_xlen_t) -> u8 {
352        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_ELT = false")));
}unreachable!("HAS_ELT = false")
353    }
354
355    /// Set to `true` to register [`get_region`](Self::get_region).
356    const HAS_GET_REGION: bool = false;
357    /// Bulk read elements into buffer.
358    fn get_region(_x: SEXP, _i: R_xlen_t, _n: R_xlen_t, _buf: &mut [u8]) -> R_xlen_t {
359        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_GET_REGION = false")));
}unreachable!("HAS_GET_REGION = false")
360    }
361}
362// endregion
363
364// region: ALTCOMPLEX - Complex vector methods
365
366/// Complex vector methods.
367pub trait AltComplex: AltVec {
368    /// Set to `true` to register [`elt`](Self::elt).
369    const HAS_ELT: bool = false;
370    /// Get element at index.
371    fn elt(_x: SEXP, _i: R_xlen_t) -> Rcomplex {
372        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_ELT = false")));
}unreachable!("HAS_ELT = false")
373    }
374
375    /// Set to `true` to register [`get_region`](Self::get_region).
376    const HAS_GET_REGION: bool = false;
377    /// Bulk read elements into buffer.
378    fn get_region(_x: SEXP, _i: R_xlen_t, _n: R_xlen_t, _buf: &mut [Rcomplex]) -> R_xlen_t {
379        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_GET_REGION = false")));
}unreachable!("HAS_GET_REGION = false")
380    }
381}
382// endregion
383
384// region: ALTSTRING - String vector methods
385
386/// String vector methods.
387///
388/// **REQUIRED**: `elt` must be implemented (no default).
389/// R will error with "No Elt method found" if you don't provide it.
390pub trait AltString: AltVec {
391    // --- REQUIRED for ALTSTRING ---
392    /// Get string element at index. Returns CHARSXP.
393    /// This is REQUIRED for ALTSTRING - there is no default.
394    fn elt(x: SEXP, i: R_xlen_t) -> SEXP;
395
396    // --- OPTIONAL ---
397    /// Set to `true` to register [`set_elt`](Self::set_elt).
398    const HAS_SET_ELT: bool = false;
399    /// Set element (for mutable strings).
400    fn set_elt(_x: SEXP, _i: R_xlen_t, _v: SEXP) {
401        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_SET_ELT = false")));
}unreachable!("HAS_SET_ELT = false")
402    }
403
404    /// Set to `true` to register [`is_sorted`](Self::is_sorted).
405    const HAS_IS_SORTED: bool = false;
406    /// Sortedness hint.
407    fn is_sorted(_x: SEXP) -> i32 {
408        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_IS_SORTED = false")));
}unreachable!("HAS_IS_SORTED = false")
409    }
410
411    /// Set to `true` to register [`no_na`](Self::no_na).
412    const HAS_NO_NA: bool = false;
413    /// NA-free hint.
414    fn no_na(_x: SEXP) -> i32 {
415        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_NO_NA = false")));
}unreachable!("HAS_NO_NA = false")
416    }
417}
418// endregion
419
420// region: ALTLIST - List (VECSXP) methods
421
422/// List vector methods.
423///
424/// **REQUIRED**: `elt` must be implemented (no default).
425/// R will error with "must provide an Elt method" if you don't provide it.
426pub trait AltList: AltVec {
427    // --- REQUIRED for ALTLIST ---
428    /// Get list element at index. Returns any SEXP.
429    /// This is REQUIRED for ALTLIST - there is no default.
430    fn elt(x: SEXP, i: R_xlen_t) -> SEXP;
431
432    // --- OPTIONAL ---
433    /// Set to `true` to register [`set_elt`](Self::set_elt).
434    const HAS_SET_ELT: bool = false;
435    /// Set element (for mutable lists).
436    fn set_elt(_x: SEXP, _i: R_xlen_t, _v: SEXP) {
437        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("HAS_SET_ELT = false")));
}unreachable!("HAS_SET_ELT = false")
438    }
439}
440// endregion
441
442// region: Constants
443
444/// Unknown sortedness value (INT_MIN in R).
445pub const UNKNOWN_SORTEDNESS: i32 = i32::MIN;
446
447/// Known to be unsorted (`KNOWN_UNSORTED` in R).
448pub const KNOWN_UNSORTED: i32 = 0;
449
450/// Sorted in increasing order, possibly with ties (`SORTED_INCR` in R).
451pub const SORTED_INCR: i32 = 1;
452
453/// Sorted in decreasing order, possibly with ties (`SORTED_DECR` in R).
454pub const SORTED_DECR: i32 = -1;
455
456/// Sorted in increasing order, with NAs first (`SORTED_INCR_NA_1ST` in R).
457pub const SORTED_INCR_NA_1ST: i32 = 2;
458
459/// Sorted in decreasing order, with NAs first (`SORTED_DECR_NA_1ST` in R).
460pub const SORTED_DECR_NA_1ST: i32 = -2;
461/// NA value for integers.
462pub const NA_INTEGER: i32 = i32::MIN;
463/// NA value for logical (same as integer in R).
464pub const NA_LOGICAL: i32 = i32::MIN;
465/// NA value for reals (IEEE NaN with R's NA payload).
466pub const NA_REAL: f64 = f64::from_bits(0x7FF0_0000_0000_07A2);
467// endregion