Skip to main content

miniextendr_macros/
altrep_derive.rs

1//! Derive macros for ALTREP data traits.
2//!
3//! These macros auto-implement `AltrepLen` and `Alt*Data` traits for simple field-based
4//! ALTREP types, reducing boilerplate for users.
5//!
6//! # Two paths: field-based vs manual
7//!
8//! `#[derive(AltrepInteger)]` (and the `Real` / `Logical` / `Raw` / `String`
9//! / `Complex` / `List` variants) drive one of two code paths:
10//!
11//! 1. **Field-based** *(default)* — point the derive at struct fields that
12//!    hold the vector length and a constant element value:
13//!
14//!    ```ignore
15//!    #[derive(AltrepInteger)]
16//!    #[altrep(len = "n", elt = "value", class = "Repeat")]
17//!    struct Repeat { n: usize, value: i32 }
18//!    ```
19//!
20//!    The derive emits `AltrepLen`, `AltIntegerData`, `Altrep`, `AltVec`,
21//!    `RegisterAltrep`, and the `R_make_altinteger_class` registration. No
22//!    extra trait impls required.
23//!
24//! 2. **Manual** — `#[altrep(manual)]` suppresses `AltrepLen` /
25//!    `AltIntegerData` generation so you can write the element-access logic
26//!    yourself. The low-level trait impls (`Altrep`, `AltVec`, family
27//!    methods, `InferBase`) are still emitted — `#[altrep(no_lowlevel)]` is
28//!    the additional escape hatch when you also want to control `Altrep` /
29//!    `AltVec` directly.
30//!
31//! Pick by what your data looks like: a finite buffer that fits in a struct
32//! field → field-based; a computed element (`fibonacci(i)`) → manual.
33//!
34//! # Guard mode attribute
35//!
36//! The derive recognises `#[altrep(unsafe)]` / `#[altrep(rust_unwind)]` /
37//! `#[altrep(r_unwind)]` on the struct, which sets the runtime
38//! `Altrep::GUARD` const that the trampolines in `altrep_bridge` dispatch
39//! on. Default is `r_unwind` (safe for callbacks that call R APIs).
40//!
41//! # Derive validation rules
42//!
43//! Several `#[altrep(...)]` options conflict; the derive rejects illegal
44//! combinations at compile time:
45//!
46//! | Option | Allowed on families | Conflicts with |
47//! |---|---|---|
48//! | `subset` | all atomic (integer, real, logical, raw, string, complex) | `dataptr`, `list` |
49//! | `dataptr` | integer, real, logical, raw, string, complex | `subset`, `list` |
50//! | `serialize` | all | (none) |
51//! | `manual` | all | (none — turns off `AltrepLen`/`Alt*Data` generation) |
52//! | `no_lowlevel` | all | (none — also suppresses the low-level trait impls) |
53//!
54//! The list family rejects `dataptr` and `subset` — list elements are
55//! arbitrary SEXPs, so there is no contiguous buffer to expose.
56
57use proc_macro2::TokenStream;
58use quote::quote;
59use syn::spanned::Spanned;
60
61/// Per-family configuration controlling low-level code generation for an ALTREP type family.
62///
63/// Each ALTREP family (integer, real, logical, raw, string, complex, list) has a distinct
64/// set of runtime macros for trait implementations and different capabilities (e.g., only
65/// some families support `dataptr` or `subset`). This struct captures those differences
66/// so [`AltrepAttrs::generate_lowlevel`] can emit the correct code.
67struct AltrepFamilyConfig<'a> {
68    /// Human-readable family name used in option-validation error messages
69    /// (e.g., `"AltrepInteger"`).
70    family_name: &'a str,
71    /// If this family supports a typed `dataptr` materialization macro, the tuple contains:
72    /// - The macro name (e.g., `"__impl_altvec_dataptr"`)
73    /// - An optional element type token stream (e.g., `i32` for integer, `f64` for real)
74    ///
75    /// `None` means this family does not have a typed dataptr macro (e.g., list).
76    dataptr_macro: Option<(&'a str, Option<TokenStream>)>,
77    /// Whether this family supports the string-specific dataptr materialization macro
78    /// (`__impl_altvec_string_dataptr`). Only `true` for the String family.
79    string_dataptr: bool,
80    /// Whether this family supports the `subset` option for `Extract_subset` method
81    /// registration. `false` for List (which rejects `subset` and `dataptr`).
82    subset: bool,
83    /// Name of the internal macro for type-specific method implementations
84    /// (e.g., `"__impl_altinteger_methods"` for integer).
85    methods_macro: &'a str,
86    /// Name of the `impl_inferbase_*!` macro that provides `InferBase` for this family
87    /// (e.g., `"impl_inferbase_integer"`).
88    inferbase_macro: &'a str,
89    /// Default guard mode for this family when no explicit guard is specified.
90    /// String family uses `RUnwind` because elt/dataptr call R APIs (Rf_mkCharLenCE).
91    /// All families now default to `RUnwind`.
92    default_guard: &'a str,
93    /// Family-specific materializing dataptr macro (e.g.
94    /// `"__impl_altvec_integer_dataptr"`). The default/serialize arms use it
95    /// to install the trivial `AltrepDataptr` + materializing `AltVec`.
96    materializing_dataptr_macro: &'a str,
97}
98
99/// Parsed `#[altrep(...)]` attributes controlling ALTREP derive code generation.
100///
101/// These attributes are placed on the struct and parsed by all ALTREP derive macros
102/// (`AltrepInteger`, `AltrepReal`, etc.) to customize the generated trait implementations.
103///
104/// # Supported `#[altrep(...)]` keys
105///
106/// | Key | Type | Description |
107/// |-----|------|-------------|
108/// | `len = "field"` | `String` | Name of the struct field that holds the vector length. Auto-detected if a field is named `len` or `length`. |
109/// | `elt = "field"` | `String` | Name of the struct field to return as the element value (produces a constant-value vector). If omitted, the default `elt()` returns `NA` / `NaN` / `0` / `None` depending on the family. |
110/// | `manual` | Flag | Skip automatic `AltrepLen` and `Alt*Data` trait generation. Use when you want to write those trait impls by hand (e.g., for custom `elt` logic, `no_na`, `sum`, etc.). The low-level trait impls (`Altrep`, `AltVec`, family methods, `InferBase`) are still emitted automatically — you do **not** need to write them yourself. Use `no_lowlevel` as an additional escape hatch if you also want to suppress those. |
111/// | `no_lowlevel` | Flag | Suppress the automatic low-level trait impls. Use this when you want to provide your own `Altrep`, `AltVec`, and family-specific trait implementations. |
112/// | `dataptr` | Flag | Enable `Dataptr` method registration, allowing R to get a direct pointer to the underlying data. Mutually exclusive with `subset`. Not supported for List. |
113/// | `serialize` | Flag | Enable `Serialized_state` and `Unserialize` method registration for ALTREP serialization support. |
114/// | `duplicate = "clone"` | String | Keep ALTREP on duplication: clone the owner (requires `Clone`) and copy the R cache. Omission retains R's default, which materializes an ordinary vector. |
115/// | `subset` | Flag | Enable `Extract_subset` method registration. Mutually exclusive with `dataptr`. Supported on all atomic families. Not supported for List. |
116/// | `unsafe` | Flag | Set native-read guard to `Unsafe` -- no panic protection. Allocating bridges stay protected. |
117/// | `rust_unwind` | Flag | Set native-read guard to `RustUnwind` -- `catch_unwind` only; reads must not call fallible R APIs. |
118/// | `r_unwind` | Flag | Set guard mode to `RUnwind` (default) -- uses `with_r_unwind_protect` for safe R API calls. |
119/// | `class = "name"` | `String` | Override the ALTREP class name (default: struct name). |
120struct AltrepAttrs {
121    /// Field name containing the vector length, set via `#[altrep(len = "field")]`.
122    /// If `None`, auto-detection looks for fields named `len` or `length`.
123    len_field: Option<syn::Ident>,
124    /// Field name for constant-value element access, set via `#[altrep(elt = "field")]`.
125    /// When set, `elt()` returns `self.{field}` for every index.
126    elt_field: Option<syn::Ident>,
127    /// Field name for delegated element access, set via `#[altrep(elt_delegate = "field")]`.
128    /// When set, `elt()` calls `self.{field}.elt(i)`, delegating to the inner type's
129    /// `AltIntegerData`/`AltRealData`/etc. implementation. Useful for wrapper types
130    /// around `StreamingIntData`, `StreamingRealData`, etc.
131    elt_delegate: Option<syn::Ident>,
132    /// Whether to generate the low-level trait impls (`Altrep`, `AltVec`,
133    /// family methods, `InferBase`). Defaults to `true`. Set to `false` by
134    /// `#[altrep(no_lowlevel)]`.
135    generate_lowlevel: bool,
136    /// Collected option flags (`dataptr`, `serialize`, `subset`) passed to the runtime macro.
137    lowlevel_options: Vec<syn::Ident>,
138    /// Guard mode override for ALTREP trampoline callbacks. Maps to `AltrepGuard` variants:
139    /// - `Unsafe` -- no protection
140    /// - `RustUnwind` -- `catch_unwind` only
141    /// - `RUnwind` -- `with_r_unwind_protect` (default)
142    guard: Option<syn::Ident>,
143    /// Override the ALTREP class name. Default: struct name.
144    class_name: Option<String>,
145    /// Manual mode: skip `AltrepLen` and `Alt*Data` generation. User provides their own.
146    /// Set by `#[altrep(manual)]`. Lowlevel traits + registration still generated.
147    manual: bool,
148    /// Opt-in duplicate policy; absent retains R's materializing default.
149    duplicate: Option<syn::LitStr>,
150}
151
152impl AltrepAttrs {
153    /// Parses all `#[altrep(...)]` attributes from a derive input struct.
154    ///
155    /// Multiple `#[altrep(...)]` attributes are supported and their contents are merged.
156    /// Unknown keys produce a compile error.
157    ///
158    /// # Errors
159    ///
160    /// Returns `Err` if an `#[altrep(...)]` attribute has malformed syntax or contains
161    /// an unknown key.
162    fn parse(input: &syn::DeriveInput) -> syn::Result<Self> {
163        let mut len_field = None;
164        let mut elt_field = None;
165        let mut elt_delegate = None;
166        let mut generate_lowlevel = true; // Default: generate
167        let mut lowlevel_options = Vec::new();
168        let mut guard = None;
169        let mut class_name = None;
170        let mut manual = false;
171        let mut duplicate = None;
172
173        for attr in &input.attrs {
174            if !attr.path().is_ident("altrep") {
175                continue;
176            }
177
178            attr.parse_nested_meta(|meta| {
179                if meta.path.is_ident("len") {
180                    let _: ::syn::token::Eqsyn::Token![=] = meta.input.parse()?;
181                    let field: syn::LitStr = meta.input.parse()?;
182                    len_field = Some(syn::Ident::new(&field.value(), field.span()));
183                } else if meta.path.is_ident("elt") {
184                    let _: ::syn::token::Eqsyn::Token![=] = meta.input.parse()?;
185                    let field: syn::LitStr = meta.input.parse()?;
186                    elt_field = Some(syn::Ident::new(&field.value(), field.span()));
187                } else if meta.path.is_ident("elt_delegate") {
188                    let _: ::syn::token::Eqsyn::Token![=] = meta.input.parse()?;
189                    let field: syn::LitStr = meta.input.parse()?;
190                    elt_delegate = Some(syn::Ident::new(&field.value(), field.span()));
191                } else if meta.path.is_ident("duplicate") {
192                    if duplicate.is_some() {
193                        return Err(meta.error("duplicate `duplicate` policy"));
194                    }
195                    let policy: syn::LitStr = meta.value()?.parse()?;
196                    if policy.value() != "clone" {
197                        return Err(syn::Error::new(
198                            policy.span(),
199                            "duplicate policy must be `clone`",
200                        ));
201                    }
202                    duplicate = Some(policy);
203                } else if meta.path.is_ident("no_lowlevel") {
204                    generate_lowlevel = false;
205                } else if meta.path.is_ident("manual") {
206                    manual = true;
207                } else if meta.path.is_ident("class") {
208                    let _: ::syn::token::Eqsyn::Token![=] = meta.input.parse()?;
209                    let name: syn::LitStr = meta.input.parse()?;
210                    class_name = Some(name.value());
211                } else if meta.path.is_ident("dataptr") {
212                    lowlevel_options.push(syn::Ident::new("dataptr", meta.path.span()));
213                } else if meta.path.is_ident("serialize") {
214                    lowlevel_options.push(syn::Ident::new("serialize", meta.path.span()));
215                } else if meta.path.is_ident("subset") {
216                    lowlevel_options.push(syn::Ident::new("subset", meta.path.span()));
217                } else if meta.path.is_ident("r#unsafe") || meta.path.is_ident("unsafe") {
218                    guard = Some(syn::Ident::new("Unsafe", meta.path.span()));
219                } else if meta.path.is_ident("rust_unwind") {
220                    guard = Some(syn::Ident::new("RustUnwind", meta.path.span()));
221                } else if meta.path.is_ident("r_unwind") {
222                    guard = Some(syn::Ident::new("RUnwind", meta.path.span()));
223                } else {
224                    return Err(meta.error(
225                        "unknown #[altrep(...)] attribute; expected one of: \
226                         `len`, `elt`, `elt_delegate`, `manual`, `no_lowlevel`, `class`, \
227                         `dataptr`, `serialize`, `subset`, `duplicate`, `unsafe`, \
228                         `rust_unwind`, `r_unwind`",
229                    ));
230                }
231                Ok(())
232            })?;
233        }
234
235        if !generate_lowlevel && let Some(policy) = &duplicate {
236            return Err(syn::Error::new(
237                policy.span(),
238                "`duplicate` requires generated low-level traits; remove `no_lowlevel`",
239            ));
240        }
241        Ok(Self {
242            len_field,
243            elt_field,
244            elt_delegate,
245            generate_lowlevel,
246            lowlevel_options,
247            guard,
248            class_name,
249            manual,
250            duplicate,
251        })
252    }
253
254    /// Extra methods in the existing base impl; R's DuplicateEX still copies
255    /// attributes and object flags around this Duplicate hook.
256    fn duplicate_methods(&self) -> TokenStream {
257        if self.duplicate.is_none() {
258            return ::quote::__private::TokenStream::new()quote! {};
259        }
260        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_comma(&mut _s);
    ::quote::__private::push_ident(&mut _s, "extra");
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "const");
            ::quote::__private::push_ident(&mut _s, "HAS_DUPLICATE");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "bool");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_ident(&mut _s, "true");
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "duplicate");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "x");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "SEXP");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "_deep");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "bool");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "altrep_impl");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s,
                                "duplicate_altrep_owner");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_gt(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "x");
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
261            , extra = {
262                const HAS_DUPLICATE: bool = true;
263                fn duplicate(x: ::miniextendr_api::SEXP, _deep: bool) -> ::miniextendr_api::SEXP {
264                    unsafe { ::miniextendr_api::altrep_impl::duplicate_altrep_owner::<Self>(x) }
265                }
266            }
267        }
268    }
269
270    /// Returns the length field identifier, either from the explicit `len = "..."` attribute
271    /// or by auto-detecting a field named `len` or `length` on the struct.
272    ///
273    /// # Errors
274    ///
275    /// Returns `Err` if the input is not a struct, or if no length field was specified
276    /// and auto-detection fails.
277    fn get_len_field(&self, input: &syn::DeriveInput) -> syn::Result<syn::Ident> {
278        if let Some(ref field) = self.len_field {
279            return Ok(field.clone());
280        }
281
282        // Try to auto-detect: look for field named "len" or "length"
283        let fields = match &input.data {
284            syn::Data::Struct(data_struct) => &data_struct.fields,
285            _ => {
286                return Err(syn::Error::new(
287                    input.span(),
288                    "Altrep derive only supports structs",
289                ));
290            }
291        };
292
293        for field in fields {
294            if let Some(ident) = &field.ident
295                && (ident == "len" || ident == "length")
296            {
297                return Ok(ident.clone());
298            }
299        }
300
301        Err(syn::Error::new(
302            input.span(),
303            "no length field found; specify with #[altrep(len = \"field_name\")]",
304        ))
305    }
306
307    /// Validates that the requested `#[altrep(...)]` option flags are compatible with
308    /// the given ALTREP type family.
309    ///
310    /// Enforces two rules:
311    /// 1. `subset` is only valid for families where `supports_subset` is `true`.
312    /// 2. `dataptr` and `subset` are mutually exclusive.
313    ///
314    /// # Arguments
315    ///
316    /// * `family` -- A human-readable family name used in error messages (e.g., `"AltrepList"`).
317    /// * `supports_subset` -- Whether this family supports the `Extract_subset` method.
318    ///
319    /// # Errors
320    ///
321    /// Returns `Err` with a span pointing to the offending option identifier.
322    fn validate_options(&self, family: &str, supports_subset: bool) -> syn::Result<()> {
323        let has_dataptr = self.lowlevel_options.iter().any(|o| o == "dataptr");
324        let has_subset = self.lowlevel_options.iter().any(|o| o == "subset");
325
326        if has_subset && !supports_subset {
327            return Err(syn::Error::new(
328                self.lowlevel_options
329                    .iter()
330                    .find(|o| *o == "subset")
331                    .unwrap()
332                    .span(),
333                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`subset` is not supported for {0}",
                family))
    })format!("`subset` is not supported for {family}"),
334            ));
335        }
336
337        if has_dataptr && has_subset {
338            return Err(syn::Error::new(
339                self.lowlevel_options
340                    .iter()
341                    .find(|o| *o == "subset")
342                    .unwrap()
343                    .span(),
344                "`dataptr` and `subset` are mutually exclusive",
345            ));
346        }
347
348        Ok(())
349    }
350
351    /// Generates low-level ALTREP trait implementation code for a given type family.
352    ///
353    /// Emits the underlying trait-impl macros directly (Path (a) from #682,
354    /// landed via #711/#933), reproducing the `impl_alt<family>_from_data!`
355    /// arm expansions from the proc-macro with no declarative-macro hop. The
356    /// four items every arm produces are:
357    ///
358    /// 1. `__impl_altrep_base!(Ty, <guard>[, with_serialize])` — `impl Altrep`.
359    /// 2. an `AltVec` impl, one of:
360    ///    - materializing (`materializing_dataptr_macro`) — default/serialize arms,
361    ///    - direct dataptr (`__impl_altvec_dataptr!(Ty, <elem>)`; string routes
362    ///      through `__impl_altvec_string_dataptr!`) — `dataptr` arm,
363    ///    - subset (`__impl_altvec_extract_subset!`) — `subset` arm,
364    /// 3. `methods_macro!(Ty)` — the family `Alt<Family>` impl,
365    /// 4. `inferbase_macro!(Ty)` — `impl InferBase`.
366    ///
367    /// The guard is honoured uniformly (the retired declarative-macro
368    /// delegation only handled the default `RUnwind` guard; non-default guards
369    /// used a separate expanded path) and option combinations are validated
370    /// here at the derive call site rather than 7 hops deep in macro
371    /// expansion.
372    ///
373    /// # Arguments
374    ///
375    /// * `name` -- The struct identifier.
376    /// * `family` -- The family-specific configuration controlling which macros to emit.
377    ///
378    /// # Returns
379    ///
380    /// A token stream containing the macro invocations, or an empty stream if
381    /// `no_lowlevel` was specified.
382    ///
383    /// # Errors
384    ///
385    /// Returns `Err` if option validation fails (e.g., `subset` on an
386    /// unsupported family, or `dataptr` combined with `subset`).
387    fn generate_lowlevel(
388        &self,
389        name: &syn::Ident,
390        generics: &syn::Generics,
391        family: &AltrepFamilyConfig,
392    ) -> syn::Result<TokenStream> {
393        let (_, ty_generics, _) = generics.split_for_impl();
394        let AltrepFamilyConfig {
395            family_name,
396            ref dataptr_macro,
397            string_dataptr,
398            subset,
399            methods_macro,
400            inferbase_macro,
401            default_guard,
402            materializing_dataptr_macro,
403        } = *family;
404
405        if !self.generate_lowlevel {
406            return Ok(::quote::__private::TokenStream::new()quote! {});
407        }
408
409        self.validate_options(family_name, subset)?;
410
411        let has_serialize = self.lowlevel_options.iter().any(|o| o == "serialize");
412        let has_dataptr = self.lowlevel_options.iter().any(|o| o == "dataptr");
413        let has_subset = self.lowlevel_options.iter().any(|o| o == "subset");
414
415        let guard = self
416            .guard
417            .as_ref()
418            .cloned()
419            .unwrap_or_else(|| syn::Ident::new(default_guard, proc_macro2::Span::call_site()));
420
421        // 1. Altrep base. The declarative macro's default/dataptr/subset arms use
422        //    `__impl_altrep_base!($ty)` (default RUnwind guard); the `*serialize`
423        //    arms use `__impl_altrep_base!($ty, with_serialize)`. We additionally
424        //    thread an explicit guard so non-default guards no longer need a
425        //    separate code path.
426        let duplicate = self.duplicate_methods();
427        let base_impl = if has_serialize {
428            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__impl_altrep_base");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&guard, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "with_serialize");
            ::quote::ToTokens::to_tokens(&duplicate, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::__impl_altrep_base!(#name #ty_generics, #guard, with_serialize #duplicate); }
429        } else {
430            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__impl_altrep_base");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&guard, &mut _s);
            ::quote::ToTokens::to_tokens(&duplicate, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::__impl_altrep_base!(#name #ty_generics, #guard #duplicate); }
431        };
432
433        // 2. AltVec impl. Mirrors the per-arm choice in `impl_alt<family>_from_data!`:
434        //    - `dataptr` arm -> direct `__impl_altvec_dataptr!($ty, $elem)`; the
435        //      string family has no typed contiguous pointer, so its `dataptr`
436        //      arm routes through `__impl_altvec_string_dataptr!` (whole-vector
437        //      STRSXP materialization — same emission as its default arm),
438        //    - `subset` arm  -> `__impl_altvec_extract_subset!`,
439        //    - default / serialize arms -> the family materializing dataptr macro
440        //      (e.g. `__impl_altvec_integer_dataptr!`), which installs a trivial
441        //      `AltrepDataptr` returning `None` then delegates to
442        //      `__impl_altvec_dataptr!`.
443        let vec_impl = if has_dataptr {
444            if string_dataptr {
445                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__impl_altvec_string_dataptr");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::__impl_altvec_string_dataptr!(#name #ty_generics); }
446            } else {
447                let (macro_name, elem_ty) = dataptr_macro
448                    .as_ref()
449                    .expect("emit_direct family must define a typed dataptr macro");
450                let dp_macro = syn::Ident::new(macro_name, proc_macro2::Span::call_site());
451                let elem = elem_ty
452                    .as_ref()
453                    .expect("emit_direct dataptr macro must carry an element type");
454                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::ToTokens::to_tokens(&dp_macro, &mut _s);
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&elem, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::#dp_macro!(#name #ty_generics, #elem); }
455            }
456        } else if has_subset {
457            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__impl_altvec_extract_subset");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::__impl_altvec_extract_subset!(#name #ty_generics); }
458        } else {
459            let mat_macro =
460                syn::Ident::new(materializing_dataptr_macro, proc_macro2::Span::call_site());
461            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::ToTokens::to_tokens(&mat_macro, &mut _s);
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::#mat_macro!(#name #ty_generics); }
462        };
463
464        // 3. Family method impl (`impl Alt<Family>`).
465        let methods_ident = syn::Ident::new(methods_macro, proc_macro2::Span::call_site());
466        let methods_impl = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::ToTokens::to_tokens(&methods_ident, &mut _s);
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::#methods_ident!(#name #ty_generics); };
467
468        // 4. InferBase.
469        let inferbase_ident = syn::Ident::new(inferbase_macro, proc_macro2::Span::call_site());
470        let inferbase_impl = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::ToTokens::to_tokens(&inferbase_ident, &mut _s);
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::#inferbase_ident!(#name #ty_generics); };
471
472        Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&base_impl, &mut _s);
    ::quote::ToTokens::to_tokens(&vec_impl, &mut _s);
    ::quote::ToTokens::to_tokens(&methods_impl, &mut _s);
    ::quote::ToTokens::to_tokens(&inferbase_impl, &mut _s);
    _s
}quote! {
473            #base_impl
474            #vec_impl
475            #methods_impl
476            #inferbase_impl
477        })
478    }
479}
480
481/// Generates an `impl AltrepLen for T` block that delegates to a named struct field.
482///
483/// The generated implementation returns `self.{len_field}` cast to `usize` as the
484/// ALTREP vector length.
485///
486/// # Arguments
487///
488/// * `name` -- The struct identifier.
489/// * `generics` -- Generic parameters for the struct.
490/// * `len_field` -- The identifier of the field that holds the length value.
491fn generate_altrep_len(
492    name: &syn::Ident,
493    generics: &syn::Generics,
494    len_field: &syn::Ident,
495) -> TokenStream {
496    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
497
498    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltrepLen");
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "altrep_len");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::ToTokens::to_tokens(&len_field, &mut _s);
                    _s
                });
            _s
        });
    _s
}quote! {
499        impl #impl_generics ::miniextendr_api::altrep_data::AltrepLen for #name #ty_generics #where_clause {
500            fn altrep_len(&self) -> usize {
501                self.#len_field
502            }
503        }
504    }
505}
506
507/// Shared implementation for all non-list ALTREP derive macros.
508///
509/// Generates three items:
510/// 1. `impl AltrepLen` -- delegates to the detected/specified length field
511/// 2. `impl Alt*Data` -- the family-specific data trait with an `elt()` method
512/// 3. Low-level trait impls via [`AltrepAttrs::generate_lowlevel`]
513///
514/// # Arguments
515///
516/// * `input` -- The `DeriveInput` from the proc-macro.
517/// * `data_trait_path` -- The fully qualified path to the data trait
518///   (e.g., `::miniextendr_api::altrep_data::AltIntegerData`).
519/// * `gen_elt_impl` -- A closure that receives the optional `elt_field` and returns
520///   a token stream for the `fn elt(...)` method body. If `elt_field` is `Some`, the
521///   closure typically returns `self.{field}`; if `None`, it returns a family-appropriate
522///   default (`NA_INTEGER`, `f64::NAN`, `0u8`, `Logical::Na`, `None`, or `Rcomplex { NAN, NAN }`).
523/// * `family` -- The [`AltrepFamilyConfig`] for this type family.
524///
525/// # Errors
526///
527/// Returns `Err` if attribute parsing fails, no length field can be found, or
528/// option validation fails.
529fn derive_altrep_generic(
530    input: syn::DeriveInput,
531    data_trait_path: TokenStream,
532    gen_elt_impl: impl FnOnce(Option<&syn::Ident>, Option<&syn::Ident>) -> TokenStream,
533    family: &AltrepFamilyConfig,
534) -> syn::Result<TokenStream> {
535    let name = &input.ident;
536    let generics = &input.generics;
537    let attrs = AltrepAttrs::parse(&input)?;
538
539    // In manual mode, skip AltrepLen + data trait generation — user provides their own.
540    let data_traits = if attrs.manual {
541        ::quote::__private::TokenStream::new();quote! {}
542    } else {
543        let len_field = attrs.get_len_field(&input)?;
544        let altrep_len_impl = generate_altrep_len(name, generics, &len_field);
545        let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
546        let elt_impl = gen_elt_impl(attrs.elt_field.as_ref(), attrs.elt_delegate.as_ref());
547        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&altrep_len_impl, &mut _s);
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::ToTokens::to_tokens(&data_trait_path, &mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&elt_impl, &mut _s);
            _s
        });
    _s
}quote! {
548            #altrep_len_impl
549            impl #impl_generics #data_trait_path for #name #ty_generics #where_clause {
550                #elt_impl
551            }
552        }
553    };
554
555    let lowlevel_impl = attrs.generate_lowlevel(name, generics, family)?;
556
557    // Generate full registration (TypedExternal, AltrepClass, RegisterAltrep, IntoR,
558    // linkme entry, Ref/Mut).
559    let class_name = attrs
560        .class_name
561        .as_deref()
562        .unwrap_or(&name.to_string())
563        .to_string();
564    let registration_impl =
565        crate::altrep::generate_direct_altrep_registration(&input, &class_name)?;
566
567    Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&data_traits, &mut _s);
    ::quote::ToTokens::to_tokens(&lowlevel_impl, &mut _s);
    ::quote::ToTokens::to_tokens(&registration_impl, &mut _s);
    _s
}quote! {
568        #data_traits
569        #lowlevel_impl
570        #registration_impl
571    })
572}
573
574/// Derive macro entry point for `AltrepInteger`.
575///
576/// Auto-implements `AltrepLen` and `AltIntegerData` for a struct with a length field.
577/// The `elt()` method returns `self.{elt_field}` as `i32` if `#[altrep(elt = "...")]`
578/// is specified, or `NA_INTEGER` by default.
579///
580/// Supports `#[altrep(dataptr)]` for direct `i32` data pointer access and
581/// `#[altrep(subset)]` for `Extract_subset`.
582pub fn derive_altrep_integer(input: syn::DeriveInput) -> syn::Result<TokenStream> {
583    derive_altrep_generic(
584        input,
585        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltIntegerData");
    _s
}quote! { ::miniextendr_api::altrep_data::AltIntegerData },
586        |elt_field, elt_delegate| {
587            if let Some(d) = elt_delegate {
588                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "i32");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&d, &mut _s);
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            _s
        });
    _s
}quote! { fn elt(&self, i: usize) -> i32 { self.#d.elt(i) } }
589            } else if let Some(f) = elt_field {
590                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "i32");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&f, &mut _s);
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> i32 { self.#f } }
591            } else {
592                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "i32");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "altrep_traits");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "NA_INTEGER");
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> i32 { ::miniextendr_api::altrep_traits::NA_INTEGER } }
593            }
594        },
595        &AltrepFamilyConfig {
596            family_name: "AltrepInteger",
597            dataptr_macro: Some(("__impl_altvec_dataptr", Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "i32");
    _s
}quote! { i32 }))),
598            string_dataptr: false,
599            subset: true,
600            methods_macro: "__impl_altinteger_methods",
601            inferbase_macro: "impl_inferbase_integer",
602            default_guard: "RUnwind",
603            materializing_dataptr_macro: "__impl_altvec_integer_dataptr",
604        },
605    )
606}
607
608/// Derive macro entry point for `AltrepReal`.
609///
610/// Auto-implements `AltrepLen` and `AltRealData` for a struct with a length field.
611/// The `elt()` method returns `self.{elt_field}` as `f64` if `#[altrep(elt = "...")]`
612/// is specified, or `f64::NAN` (R's `NA_real_`) by default.
613///
614/// Supports `#[altrep(dataptr)]` for direct `f64` data pointer access and
615/// `#[altrep(subset)]` for `Extract_subset`.
616pub fn derive_altrep_real(input: syn::DeriveInput) -> syn::Result<TokenStream> {
617    derive_altrep_generic(
618        input,
619        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltRealData");
    _s
}quote! { ::miniextendr_api::altrep_data::AltRealData },
620        |elt_field, elt_delegate| {
621            if let Some(d) = elt_delegate {
622                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "f64");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&d, &mut _s);
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            _s
        });
    _s
}quote! { fn elt(&self, i: usize) -> f64 { self.#d.elt(i) } }
623            } else if let Some(f) = elt_field {
624                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "f64");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&f, &mut _s);
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> f64 { self.#f } }
625            } else {
626                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "f64");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "f64");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "NAN");
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> f64 { f64::NAN } }
627            }
628        },
629        &AltrepFamilyConfig {
630            family_name: "AltrepReal",
631            dataptr_macro: Some(("__impl_altvec_dataptr", Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "f64");
    _s
}quote! { f64 }))),
632            string_dataptr: false,
633            subset: true,
634            methods_macro: "__impl_altreal_methods",
635            inferbase_macro: "impl_inferbase_real",
636            default_guard: "RUnwind",
637            materializing_dataptr_macro: "__impl_altvec_real_dataptr",
638        },
639    )
640}
641
642/// Derive macro entry point for `AltrepLogical`.
643///
644/// Auto-implements `AltrepLen` and `AltLogicalData` for a struct with a length field.
645/// The `elt()` method returns `self.{elt_field}.into()` as `Logical` if
646/// `#[altrep(elt = "...")]` is specified, or `Logical::Na` by default.
647///
648/// Supports `#[altrep(dataptr)]` for direct `i32` data pointer access (logicals are
649/// stored as `i32` in R) and `#[altrep(subset)]` for `Extract_subset`.
650pub fn derive_altrep_logical(input: syn::DeriveInput) -> syn::Result<TokenStream> {
651    derive_altrep_generic(
652        input,
653        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltLogicalData");
    _s
}quote! { ::miniextendr_api::altrep_data::AltLogicalData },
654        |elt_field, elt_delegate| {
655            if let Some(d) = elt_delegate {
656                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Logical");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&d, &mut _s);
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            _s
        });
    _s
}quote! { fn elt(&self, i: usize) -> ::miniextendr_api::altrep_data::Logical { self.#d.elt(i) } }
657            } else if let Some(f) = elt_field {
658                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Logical");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&f, &mut _s);
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> ::miniextendr_api::altrep_data::Logical { self.#f.into() } }
659            } else {
660                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Logical");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "altrep_data");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Logical");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Na");
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> ::miniextendr_api::altrep_data::Logical { ::miniextendr_api::altrep_data::Logical::Na } }
661            }
662        },
663        &AltrepFamilyConfig {
664            family_name: "AltrepLogical",
665            dataptr_macro: Some(("__impl_altvec_dataptr", Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "i32");
    _s
}quote! { i32 }))),
666            string_dataptr: false,
667            subset: true,
668            methods_macro: "__impl_altlogical_methods",
669            inferbase_macro: "impl_inferbase_logical",
670            default_guard: "RUnwind",
671            materializing_dataptr_macro: "__impl_altvec_logical_dataptr",
672        },
673    )
674}
675
676/// Derive macro entry point for `AltrepRaw`.
677///
678/// Auto-implements `AltrepLen` and `AltRawData` for a struct with a length field.
679/// The `elt()` method returns `self.{elt_field}` as `u8` if `#[altrep(elt = "...")]`
680/// is specified, or `0u8` by default.
681///
682/// Supports `#[altrep(dataptr)]` for direct `u8` data pointer access and
683/// `#[altrep(subset)]` for `Extract_subset`.
684pub fn derive_altrep_raw(input: syn::DeriveInput) -> syn::Result<TokenStream> {
685    derive_altrep_generic(
686        input,
687        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltRawData");
    _s
}quote! { ::miniextendr_api::altrep_data::AltRawData },
688        |elt_field, elt_delegate| {
689            if let Some(d) = elt_delegate {
690                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "u8");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&d, &mut _s);
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            _s
        });
    _s
}quote! { fn elt(&self, i: usize) -> u8 { self.#d.elt(i) } }
691            } else if let Some(f) = elt_field {
692                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "u8");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&f, &mut _s);
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> u8 { self.#f } }
693            } else {
694                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_ident(&mut _s, "u8");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::parse(&mut _s, "0");
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> u8 { 0 } }
695            }
696        },
697        &AltrepFamilyConfig {
698            family_name: "AltrepRaw",
699            dataptr_macro: Some(("__impl_altvec_dataptr", Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "u8");
    _s
}quote! { u8 }))),
700            string_dataptr: false,
701            subset: true,
702            methods_macro: "__impl_altraw_methods",
703            inferbase_macro: "impl_inferbase_raw",
704            default_guard: "RUnwind",
705            materializing_dataptr_macro: "__impl_altvec_raw_dataptr",
706        },
707    )
708}
709
710/// Derive macro entry point for `AltrepString`.
711///
712/// Auto-implements `AltrepLen` and `AltStringData` for a struct with a length field.
713/// The `elt()` method returns `Some(self.{elt_field}.as_ref())` as `Option<&str>` if
714/// `#[altrep(elt = "...")]` is specified, or `None` (R's `NA_character_`) by default.
715///
716/// String ALTREP supports `#[altrep(dataptr)]` for materialized `STRSXP` dataptr
717/// (via `__impl_altvec_string_dataptr`) and `#[altrep(subset)]` for `Extract_subset`.
718/// Note: String dataptr materializes the entire vector into a cached `STRSXP` in the
719/// data2 slot.
720pub fn derive_altrep_string(input: syn::DeriveInput) -> syn::Result<TokenStream> {
721    derive_altrep_generic(
722        input,
723        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltStringData");
    _s
}quote! { ::miniextendr_api::altrep_data::AltStringData },
724        |elt_field, elt_delegate| {
725            if let Some(d) = elt_delegate {
726                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_and(&mut _s);
    ::quote::__private::push_ident(&mut _s, "str");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&d, &mut _s);
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            _s
        });
    _s
}quote! { fn elt(&self, i: usize) -> ::core::option::Option<&str> { self.#d.elt(i) } }
727            } else if let Some(f) = elt_field {
728                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_and(&mut _s);
    ::quote::__private::push_ident(&mut _s, "str");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Some");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::ToTokens::to_tokens(&f, &mut _s);
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "as_ref");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    _s
                });
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> ::core::option::Option<&str> { ::core::option::Option::Some(self.#f.as_ref()) } }
729            } else {
730                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_and(&mut _s);
    ::quote::__private::push_ident(&mut _s, "str");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "core");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "None");
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> ::core::option::Option<&str> { ::core::option::Option::None } }
731            }
732        },
733        &AltrepFamilyConfig {
734            family_name: "AltrepString",
735            dataptr_macro: None,
736            string_dataptr: true,
737            subset: true,
738            methods_macro: "__impl_altstring_methods",
739            inferbase_macro: "impl_inferbase_string",
740            // String elt calls Rf_mkCharLenCE; dataptr calls Rf_allocVector + SET_STRING_ELT.
741            // These R API calls can longjmp — must use RUnwind.
742            default_guard: "RUnwind",
743            // String has no typed contiguous dataptr; its default/dataptr arms
744            // both route through `__impl_altvec_string_dataptr!`.
745            materializing_dataptr_macro: "__impl_altvec_string_dataptr",
746        },
747    )
748}
749
750/// Derive macro entry point for `AltrepComplex`.
751///
752/// Auto-implements `AltrepLen` and `AltComplexData` for a struct with a length field.
753/// The `elt()` method returns `self.{elt_field}` as `Rcomplex` if
754/// `#[altrep(elt = "...")]` is specified, or `Rcomplex { r: NAN, i: NAN }` by default.
755///
756/// Supports `#[altrep(dataptr)]` for direct `Rcomplex` data pointer access and
757/// `#[altrep(subset)]` for `Extract_subset`.
758pub fn derive_altrep_complex(input: syn::DeriveInput) -> syn::Result<TokenStream> {
759    derive_altrep_generic(
760        input,
761        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltComplexData");
    _s
}quote! { ::miniextendr_api::altrep_data::AltComplexData },
762        |elt_field, elt_delegate| {
763            if let Some(d) = elt_delegate {
764                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Rcomplex");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&d, &mut _s);
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            _s
        });
    _s
}quote! { fn elt(&self, i: usize) -> ::miniextendr_api::Rcomplex { self.#d.elt(i) } }
765            } else if let Some(f) = elt_field {
766                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Rcomplex");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&f, &mut _s);
            _s
        });
    _s
}quote! { fn elt(&self, _i: usize) -> ::miniextendr_api::Rcomplex { self.#f } }
767            } else {
768                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Rcomplex");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Rcomplex");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "r");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "f64");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "NAN");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "i");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "f64");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "NAN");
                    _s
                });
            _s
        });
    _s
}quote! {
769                    fn elt(&self, _i: usize) -> ::miniextendr_api::Rcomplex {
770                        ::miniextendr_api::Rcomplex { r: f64::NAN, i: f64::NAN }
771                    }
772                }
773            }
774        },
775        &AltrepFamilyConfig {
776            family_name: "AltrepComplex",
777            dataptr_macro: Some((
778                "__impl_altvec_dataptr",
779                Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Rcomplex");
    _s
}quote! { ::miniextendr_api::Rcomplex }),
780            )),
781            string_dataptr: false,
782            subset: true,
783            methods_macro: "__impl_altcomplex_methods",
784            inferbase_macro: "impl_inferbase_complex",
785            default_guard: "RUnwind",
786            materializing_dataptr_macro: "__impl_altvec_complex_dataptr",
787        },
788    )
789}
790
791/// Derive macro entry point for `AltrepList`.
792///
793/// Auto-implements `AltrepLen` and `AltListData` for a struct with a length field.
794/// The `elt()` method returns `self.{elt_field}[i]` as `SEXP` if
795/// `#[altrep(elt = "...")]` is specified (the field should be indexable and return `SEXP`),
796/// or `R_NilValue` by default.
797///
798/// List ALTREP does **not** support `#[altrep(dataptr)]` or `#[altrep(subset)]` -- both
799/// are rejected at compile time. `#[altrep(serialize)]` is supported. The class
800/// takes R's writes through `altrep_impl::altlist_set_elt`, which copies the
801/// elements into data2 on the first one; `Elt` reads data2 from then on.
802pub fn derive_altrep_list(input: syn::DeriveInput) -> syn::Result<TokenStream> {
803    let name = &input.ident;
804    let generics = &input.generics;
805    let attrs = AltrepAttrs::parse(&input)?;
806    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
807
808    // In manual mode, skip AltrepLen + AltListData generation.
809    let data_traits = if attrs.manual {
810        ::quote::__private::TokenStream::new();quote! {}
811    } else {
812        let len_field = attrs.get_len_field(&input)?;
813        let altrep_len_impl = generate_altrep_len(name, generics, &len_field);
814        let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
815
816        let elt_impl = if let Some(ref elt_field) = attrs.elt_field {
817            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&elt_field, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            _s
        });
    _s
}quote! {
818                fn elt(&self, i: usize) -> ::miniextendr_api::SEXP {
819                    self.#elt_field[i]
820                }
821            }
822        } else {
823            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "_i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "usize");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "nil");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            _s
        });
    _s
}quote! {
824                fn elt(&self, _i: usize) -> ::miniextendr_api::SEXP {
825                    ::miniextendr_api::SEXP::nil()
826                }
827            }
828        };
829
830        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&altrep_len_impl, &mut _s);
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_data");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltListData");
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&elt_impl, &mut _s);
            _s
        });
    _s
}quote! {
831            #altrep_len_impl
832            impl #impl_generics ::miniextendr_api::altrep_data::AltListData for #name #ty_generics #where_clause {
833                #elt_impl
834            }
835        }
836    };
837
838    // List does not support dataptr or subset
839    for opt in &attrs.lowlevel_options {
840        if opt == "dataptr" || opt == "subset" {
841            return Err(syn::Error::new(
842                opt.span(),
843                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is not supported for AltrepList",
                opt))
    })format!("`{opt}` is not supported for AltrepList"),
844            ));
845        }
846    }
847
848    let has_serialize = attrs.lowlevel_options.iter().any(|o| o == "serialize");
849
850    let lowlevel_impl = if !attrs.generate_lowlevel {
851        ::quote::__private::TokenStream::new();quote! {}
852    } else {
853        // Direct emit (#933). The non-serialize arm inlines the body of the
854        // retired `impl_altlist_from_data!` delegation: `__impl_altrep_base!`
855        // with an explicit guard is token-identical to that macro's
856        // hand-written `Altrep` impl, and the `elt` body matches its
857        // `altrep_extract_ref` path. The serialize arm keeps its historical
858        // `altrep_data1_as` elt body — switching it to `AltrepExtract` would
859        // change behaviour for types that override extraction.
860        let guard = attrs
861            .guard
862            .as_ref()
863            .cloned()
864            .unwrap_or_else(|| syn::Ident::new("RUnwind", proc_macro2::Span::call_site()));
865        let duplicate = attrs.duplicate_methods();
866        let base_impl = if has_serialize {
867            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__impl_altrep_base");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&guard, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "with_serialize");
            ::quote::ToTokens::to_tokens(&duplicate, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::__impl_altrep_base!(#name #ty_generics, #guard, with_serialize #duplicate); }
868        } else {
869            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__impl_altrep_base");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&guard, &mut _s);
            ::quote::ToTokens::to_tokens(&duplicate, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! { ::miniextendr_api::__impl_altrep_base!(#name #ty_generics, #guard #duplicate); }
870        };
871        // Once `Set_elt` has copied the values into data2, they are R's.
872        let written_elt = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Some");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "data2");
            _s
        });
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_ident(&mut _s, "unsafe");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "altrep_data");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s,
                "materialized_altrep_data2");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "x");
                    _s
                });
            _s
        });
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SexpExt");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "vector_elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "data2");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "i");
                    _s
                });
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    _s
}quote! {
873            if let ::core::option::Option::Some(data2) = unsafe { ::miniextendr_api::altrep_data::materialized_altrep_data2(x) } {
874                return ::miniextendr_api::SexpExt::vector_elt(&data2, i);
875            }
876        };
877        let elt_impl = if has_serialize {
878            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "x");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "R_xlen_t");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&written_elt, &mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "altrep_data1_as");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::ToTokens::to_tokens(&name, &mut _s);
                    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "x");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "map");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_or(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "d");
                    ::quote::__private::push_or(&mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::ToTokens::to_tokens(&name, &mut _s);
                    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "as");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "altrep_data");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "AltListData");
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "elt");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "unsafe");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Brace,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "d");
                                    ::quote::__private::push_dot(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "as_ref_unchecked");
                                    ::quote::__private::push_group(&mut _s,
                                        ::quote::__private::Delimiter::Parenthesis,
                                        ::quote::__private::TokenStream::new());
                                    _s
                                });
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "i");
                            ::quote::__private::push_dot(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "max");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::parse(&mut _s, "0");
                                    _s
                                });
                            ::quote::__private::push_ident(&mut _s, "as");
                            ::quote::__private::push_ident(&mut _s, "usize");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_dot(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unwrap_or");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "SEXP");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "nil");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        ::quote::__private::TokenStream::new());
                    _s
                });
            _s
        });
    _s
}quote! {
879                fn elt(x: ::miniextendr_api::SEXP, i: ::miniextendr_api::R_xlen_t) -> ::miniextendr_api::SEXP {
880                    #written_elt
881                    // No `RefCell` borrow for the ALTREP data1 read, until #2103.
882                    unsafe { ::miniextendr_api::altrep_data1_as::<#name #ty_generics>(x) }
883                        .map(|d| <#name #ty_generics as ::miniextendr_api::altrep_data::AltListData>::elt(unsafe { d.as_ref_unchecked() }, i.max(0) as usize))
884                        .unwrap_or(::miniextendr_api::SEXP::nil())
885                }
886            }
887        } else {
888            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "fn");
    ::quote::__private::push_ident(&mut _s, "elt");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "x");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "SEXP");
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_ident(&mut _s, "i");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "R_xlen_t");
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "SEXP");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&written_elt, &mut _s);
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::__private::push_ident(&mut _s, "data");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::ToTokens::to_tokens(&name, &mut _s);
                    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "as");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "altrep_data");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "AltrepExtract");
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s,
                        "altrep_extract_ref");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "x");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            ::quote::__private::push_ident(&mut _s, "as");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "altrep_data");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "AltListData");
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "data");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "i");
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "max");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::parse(&mut _s, "0");
                            _s
                        });
                    ::quote::__private::push_ident(&mut _s, "as");
                    ::quote::__private::push_ident(&mut _s, "usize");
                    _s
                });
            _s
        });
    _s
}quote! {
889                fn elt(x: ::miniextendr_api::SEXP, i: ::miniextendr_api::R_xlen_t) -> ::miniextendr_api::SEXP {
890                    #written_elt
891                    let data = unsafe {
892                        <#name #ty_generics as ::miniextendr_api::altrep_data::AltrepExtract>::altrep_extract_ref(x)
893                    };
894                    <#name #ty_generics as ::miniextendr_api::altrep_data::AltListData>::elt(data, i.max(0) as usize)
895                }
896            }
897        };
898        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&base_impl, &mut _s);
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_traits");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltVec");
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "altrep_traits");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AltList");
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&elt_impl, &mut _s);
            ::quote::__private::push_ident(&mut _s, "const");
            ::quote::__private::push_ident(&mut _s, "HAS_SET_ELT");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "bool");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_ident(&mut _s, "true");
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "set_elt");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "x");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "SEXP");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "i");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "R_xlen_t");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "v");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "SEXP");
                    _s
                });
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "miniextendr_api");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "altrep_impl");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "altlist_set_elt");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::ToTokens::to_tokens(&name, &mut _s);
                            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
                            ::quote::__private::push_gt(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "x");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "i");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "v");
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "miniextendr_api");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "impl_inferbase_list");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
899            #base_impl
900            impl #impl_generics ::miniextendr_api::altrep_traits::AltVec for #name #ty_generics #where_clause {}
901            impl #impl_generics ::miniextendr_api::altrep_traits::AltList for #name #ty_generics #where_clause {
902                #elt_impl
903
904                const HAS_SET_ELT: bool = true;
905
906                fn set_elt(x: ::miniextendr_api::SEXP, i: ::miniextendr_api::R_xlen_t, v: ::miniextendr_api::SEXP) {
907                    unsafe { ::miniextendr_api::altrep_impl::altlist_set_elt::<#name #ty_generics>(x, i, v) }
908                }
909            }
910            ::miniextendr_api::impl_inferbase_list!(#name #ty_generics);
911        }
912    };
913
914    // Generate full registration (TypedExternal, AltrepClass, RegisterAltrep, IntoR,
915    // linkme entry, Ref/Mut) — same as derive_altrep_generic.
916    let class_name = attrs
917        .class_name
918        .as_deref()
919        .unwrap_or(&name.to_string())
920        .to_string();
921    let registration_impl =
922        crate::altrep::generate_direct_altrep_registration(&input, &class_name)?;
923
924    Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&data_traits, &mut _s);
    ::quote::ToTokens::to_tokens(&lowlevel_impl, &mut _s);
    ::quote::ToTokens::to_tokens(&registration_impl, &mut _s);
    _s
}quote! {
925        #data_traits
926        #lowlevel_impl
927        #registration_impl
928    })
929}
930
931// region: Public helper for derive(Altrep) with base parameter