Skip to main content

miniextendr_api/altrep_impl/
arrays.rs

1//! ALTREP for owned const-generic arrays.
2//!
3//! The shared family generators keep native pointers and materialized data2
4//! behaviour consistent with Vec/Box. Each element family caches a separate
5//! class per N: a static inside a generic function alone would be shared by
6//! every N and install callbacks for whichever length registered first.
7//!
8//! Classes register on first conversion. Duplication and serialization keep
9//! R's default ordinary-vector fallback, so restoring a value never depends
10//! on having instantiated its array length in the receiving R session.
11
12impl<const N : usize> crate::altrep_traits::Altrep for [i32; N] where  {
    const GUARD: crate::altrep_traits::AltrepGuard =
        crate::altrep_traits::AltrepGuard::RUnwind;
    fn length(x: crate::SEXP) -> crate::R_xlen_t {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return crate::SexpExt::len(&data2) as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[i32; N] as crate::altrep_data::AltrepLen>::altrep_len(data) as
            crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_traits::AltVec for [i32; N] where  {
    const HAS_DATAPTR: bool = true;
    fn dataptr(x: crate::SEXP, writable: bool) -> *mut ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2).cast_mut();
            }
        }
        let direct =
            if writable {
                let d =
                    unsafe {
                        <[i32; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[i32; N] as
                            crate::altrep_data::AltrepDataptr<i32>>::dataptr(d,
                        true).map(|p| p.cast::<::core::ffi::c_void>())
            } else {
                let ro =
                    {
                        let d =
                            unsafe {
                                <[i32; N] as
                                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
                            };
                        <[i32; N] as
                                crate::altrep_data::AltrepDataptr<i32>>::dataptr_or_null(d)
                    };
                if let ::core::option::Option::Some(p) = ro {
                    return p.cast_mut().cast::<::core::ffi::c_void>();
                }
                let d =
                    unsafe {
                        <[i32; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[i32; N] as
                            crate::altrep_data::AltrepDataptr<i32>>::dataptr(d,
                        false).map(|p| p.cast::<::core::ffi::c_void>())
            };
        if let ::core::option::Option::Some(p) = direct { return p; }
        unsafe { crate::altrep_data::materialize_altrep_data2::<i32>(x) }
    }
    const HAS_DATAPTR_OR_NULL: bool = true;
    fn dataptr_or_null(x: crate::SEXP) -> *const ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2);
            }
        }
        let d =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[i32; N] as
                        crate::altrep_data::AltrepDataptr<i32>>::dataptr_or_null(d).map(|p|
                    p.cast::<::core::ffi::c_void>()).unwrap_or(::core::ptr::null())
    }
}
impl<const N : usize> crate::altrep_traits::AltInteger for [i32; N] where  {
    const HAS_ELT: bool = true;
    fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> i32 {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return <i32 as crate::RNativeType>::elt(data2, i.max(0));
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[i32; N] as
                crate::altrep_data::AltIntegerData>::elt(data,
            i.max(0) as usize)
    }
    const HAS_GET_REGION: bool = true;
    fn get_region(x: crate::SEXP, start: crate::R_xlen_t,
        len: crate::R_xlen_t, buf: &mut [i32]) -> crate::R_xlen_t {
        if start < 0 || len <= 0 { return 0; }
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return unsafe {
                        crate::altrep_data::materialized_altrep_region::<i32>(data2,
                            start as usize, len as usize, buf)
                    } as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let len = len as usize;
        <[i32; N] as
                    crate::altrep_data::AltIntegerData>::get_region(data,
                start as usize, len, buf) as crate::R_xlen_t
    }
    const HAS_IS_SORTED: bool = true;
    fn is_sorted(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::altrep_traits::UNKNOWN_SORTEDNESS;
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[i32; N] as
                        crate::altrep_data::AltIntegerData>::is_sorted(data).map(|s|
                    s.to_r_int()).unwrap_or(i32::MIN)
    }
    const HAS_NO_NA: bool = true;
    fn no_na(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return 0;
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[i32; N] as
                        crate::altrep_data::AltIntegerData>::no_na(data).map(|b|
                    if b { 1 } else { 0 }).unwrap_or(0)
    }
    const HAS_SUM: bool = true;
    fn sum(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        match <[i32; N] as
                    crate::altrep_data::AltIntegerData>::sum(data, narm) {
            ::core::option::Option::Some(s) => {
                if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
                    crate::SEXP::scalar_integer(s as i32)
                } else { crate::SEXP::scalar_real(s as f64) }
            }
            ::core::option::Option::None => crate::SEXP::null(),
        }
    }
    const HAS_MIN: bool = true;
    fn min(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[i32; N] as
                        crate::altrep_data::AltIntegerData>::min(data,
                    narm).map(|m|
                    crate::SEXP::scalar_integer(m)).unwrap_or(crate::SEXP::null())
    }
    const HAS_MAX: bool = true;
    fn max(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[i32; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[i32; N] as
                        crate::altrep_data::AltIntegerData>::max(data,
                    narm).map(|m|
                    crate::SEXP::scalar_integer(m)).unwrap_or(crate::SEXP::null())
    }
}
impl<const N : usize> crate::altrep_data::InferBase for [i32; N] where  {
    const BASE: crate::altrep::RBase = crate::altrep::RBase::Int;
    unsafe fn make_class(class_name: *const ::core::ffi::c_char,
        pkg_name: *const ::core::ffi::c_char)
        -> crate::sys::altrep::R_altrep_class_t {
        let dll = crate::altrep_dll_info();
        let cls =
            unsafe {
                crate::sys::altrep::R_make_altinteger_class(class_name,
                    pkg_name, dll)
            };
        let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
        crate::altrep::validate_altrep_class(cls, name,
            crate::altrep::RBase::Int)
    }
    unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
        unsafe { crate::altrep_bridge::install_base::<[i32; N]>(cls) };
        unsafe { crate::altrep_bridge::install_vec::<[i32; N]>(cls) };
        unsafe { crate::altrep_bridge::install_int::<[i32; N]>(cls) };
    }
}crate::impl_altinteger_from_data_generic!({const N: usize} [i32; N] {}, dataptr);
13impl<const N : usize> crate::altrep_traits::Altrep for [f64; N] where  {
    const GUARD: crate::altrep_traits::AltrepGuard =
        crate::altrep_traits::AltrepGuard::RUnwind;
    fn length(x: crate::SEXP) -> crate::R_xlen_t {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return crate::SexpExt::len(&data2) as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as crate::altrep_data::AltrepLen>::altrep_len(data) as
            crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_traits::AltVec for [f64; N] where  {
    const HAS_DATAPTR: bool = true;
    fn dataptr(x: crate::SEXP, writable: bool) -> *mut ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2).cast_mut();
            }
        }
        let direct =
            if writable {
                let d =
                    unsafe {
                        <[f64; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[f64; N] as
                            crate::altrep_data::AltrepDataptr<f64>>::dataptr(d,
                        true).map(|p| p.cast::<::core::ffi::c_void>())
            } else {
                let ro =
                    {
                        let d =
                            unsafe {
                                <[f64; N] as
                                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
                            };
                        <[f64; N] as
                                crate::altrep_data::AltrepDataptr<f64>>::dataptr_or_null(d)
                    };
                if let ::core::option::Option::Some(p) = ro {
                    return p.cast_mut().cast::<::core::ffi::c_void>();
                }
                let d =
                    unsafe {
                        <[f64; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[f64; N] as
                            crate::altrep_data::AltrepDataptr<f64>>::dataptr(d,
                        false).map(|p| p.cast::<::core::ffi::c_void>())
            };
        if let ::core::option::Option::Some(p) = direct { return p; }
        unsafe { crate::altrep_data::materialize_altrep_data2::<f64>(x) }
    }
    const HAS_DATAPTR_OR_NULL: bool = true;
    fn dataptr_or_null(x: crate::SEXP) -> *const ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2);
            }
        }
        let d =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as
                        crate::altrep_data::AltrepDataptr<f64>>::dataptr_or_null(d).map(|p|
                    p.cast::<::core::ffi::c_void>()).unwrap_or(::core::ptr::null())
    }
}
impl<const N : usize> crate::altrep_traits::AltReal for [f64; N] where  {
    const HAS_ELT: bool = true;
    fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> f64 {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return <f64 as crate::RNativeType>::elt(data2, i.max(0));
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as
                crate::altrep_data::AltRealData>::elt(data, i.max(0) as usize)
    }
    const HAS_GET_REGION: bool = true;
    fn get_region(x: crate::SEXP, start: crate::R_xlen_t,
        len: crate::R_xlen_t, buf: &mut [f64]) -> crate::R_xlen_t {
        if start < 0 || len <= 0 { return 0; }
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return unsafe {
                        crate::altrep_data::materialized_altrep_region::<f64>(data2,
                            start as usize, len as usize, buf)
                    } as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let len = len as usize;
        <[f64; N] as
                    crate::altrep_data::AltRealData>::get_region(data,
                start as usize, len, buf) as crate::R_xlen_t
    }
    const HAS_IS_SORTED: bool = true;
    fn is_sorted(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::altrep_traits::UNKNOWN_SORTEDNESS;
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as
                        crate::altrep_data::AltRealData>::is_sorted(data).map(|s|
                    s.to_r_int()).unwrap_or(i32::MIN)
    }
    const HAS_NO_NA: bool = true;
    fn no_na(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return 0;
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as
                        crate::altrep_data::AltRealData>::no_na(data).map(|b|
                    if b { 1 } else { 0 }).unwrap_or(0)
    }
    const HAS_SUM: bool = true;
    fn sum(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as
                        crate::altrep_data::AltRealData>::sum(data,
                    narm).map(|s|
                    crate::SEXP::scalar_real(s)).unwrap_or(crate::SEXP::null())
    }
    const HAS_MIN: bool = true;
    fn min(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as
                        crate::altrep_data::AltRealData>::min(data,
                    narm).map(|m|
                    crate::SEXP::scalar_real(m)).unwrap_or(crate::SEXP::null())
    }
    const HAS_MAX: bool = true;
    fn max(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[f64; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[f64; N] as
                        crate::altrep_data::AltRealData>::max(data,
                    narm).map(|m|
                    crate::SEXP::scalar_real(m)).unwrap_or(crate::SEXP::null())
    }
}
impl<const N : usize> crate::altrep_data::InferBase for [f64; N] where  {
    const BASE: crate::altrep::RBase = crate::altrep::RBase::Real;
    unsafe fn make_class(class_name: *const ::core::ffi::c_char,
        pkg_name: *const ::core::ffi::c_char)
        -> crate::sys::altrep::R_altrep_class_t {
        let dll = crate::altrep_dll_info();
        let cls =
            unsafe {
                crate::sys::altrep::R_make_altreal_class(class_name, pkg_name,
                    dll)
            };
        let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
        crate::altrep::validate_altrep_class(cls, name,
            crate::altrep::RBase::Real)
    }
    unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
        unsafe { crate::altrep_bridge::install_base::<[f64; N]>(cls) };
        unsafe { crate::altrep_bridge::install_vec::<[f64; N]>(cls) };
        unsafe { crate::altrep_bridge::install_real::<[f64; N]>(cls) };
    }
}crate::impl_altreal_from_data_generic!({const N: usize} [f64; N] {}, dataptr);
14impl<const N : usize> crate::altrep_traits::Altrep for [u8; N] where  {
    const GUARD: crate::altrep_traits::AltrepGuard =
        crate::altrep_traits::AltrepGuard::RUnwind;
    fn length(x: crate::SEXP) -> crate::R_xlen_t {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return crate::SexpExt::len(&data2) as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[u8; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[u8; N] as crate::altrep_data::AltrepLen>::altrep_len(data) as
            crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_traits::AltVec for [u8; N] where  {
    const HAS_DATAPTR: bool = true;
    fn dataptr(x: crate::SEXP, writable: bool) -> *mut ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2).cast_mut();
            }
        }
        let direct =
            if writable {
                let d =
                    unsafe {
                        <[u8; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[u8; N] as
                            crate::altrep_data::AltrepDataptr<u8>>::dataptr(d,
                        true).map(|p| p.cast::<::core::ffi::c_void>())
            } else {
                let ro =
                    {
                        let d =
                            unsafe {
                                <[u8; N] as
                                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
                            };
                        <[u8; N] as
                                crate::altrep_data::AltrepDataptr<u8>>::dataptr_or_null(d)
                    };
                if let ::core::option::Option::Some(p) = ro {
                    return p.cast_mut().cast::<::core::ffi::c_void>();
                }
                let d =
                    unsafe {
                        <[u8; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[u8; N] as
                            crate::altrep_data::AltrepDataptr<u8>>::dataptr(d,
                        false).map(|p| p.cast::<::core::ffi::c_void>())
            };
        if let ::core::option::Option::Some(p) = direct { return p; }
        unsafe { crate::altrep_data::materialize_altrep_data2::<u8>(x) }
    }
    const HAS_DATAPTR_OR_NULL: bool = true;
    fn dataptr_or_null(x: crate::SEXP) -> *const ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2);
            }
        }
        let d =
            unsafe {
                <[u8; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[u8; N] as
                        crate::altrep_data::AltrepDataptr<u8>>::dataptr_or_null(d).map(|p|
                    p.cast::<::core::ffi::c_void>()).unwrap_or(::core::ptr::null())
    }
}
impl<const N : usize> crate::altrep_traits::AltRaw for [u8; N] where  {
    const HAS_ELT: bool = true;
    fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> u8 {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return <u8 as crate::RNativeType>::elt(data2, i.max(0));
        }
        let data =
            unsafe {
                <[u8; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[u8; N] as
                crate::altrep_data::AltRawData>::elt(data, i.max(0) as usize)
    }
    const HAS_GET_REGION: bool = true;
    fn get_region(x: crate::SEXP, start: crate::R_xlen_t,
        len: crate::R_xlen_t, buf: &mut [u8]) -> crate::R_xlen_t {
        if start < 0 || len <= 0 { return 0; }
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return unsafe {
                        crate::altrep_data::materialized_altrep_region::<u8>(data2,
                            start as usize, len as usize, buf)
                    } as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[u8; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let len = len as usize;
        <[u8; N] as
                    crate::altrep_data::AltRawData>::get_region(data,
                start as usize, len, buf) as crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_data::InferBase for [u8; N] where  {
    const BASE: crate::altrep::RBase = crate::altrep::RBase::Raw;
    unsafe fn make_class(class_name: *const ::core::ffi::c_char,
        pkg_name: *const ::core::ffi::c_char)
        -> crate::sys::altrep::R_altrep_class_t {
        let dll = crate::altrep_dll_info();
        let cls =
            unsafe {
                crate::sys::altrep::R_make_altraw_class(class_name, pkg_name,
                    dll)
            };
        let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
        crate::altrep::validate_altrep_class(cls, name,
            crate::altrep::RBase::Raw)
    }
    unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
        unsafe { crate::altrep_bridge::install_base::<[u8; N]>(cls) };
        unsafe { crate::altrep_bridge::install_vec::<[u8; N]>(cls) };
        unsafe { crate::altrep_bridge::install_raw::<[u8; N]>(cls) };
    }
}crate::impl_altraw_from_data_generic!({const N: usize} [u8; N] {}, dataptr);
15impl<const N : usize> crate::altrep_traits::Altrep for [crate::Rcomplex; N]
    where  {
    const GUARD: crate::altrep_traits::AltrepGuard =
        crate::altrep_traits::AltrepGuard::RUnwind;
    fn length(x: crate::SEXP) -> crate::R_xlen_t {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return crate::SexpExt::len(&data2) as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[crate::Rcomplex; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[crate::Rcomplex; N] as
                    crate::altrep_data::AltrepLen>::altrep_len(data) as
            crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_traits::AltVec for [crate::Rcomplex; N]
    where  {
    const HAS_DATAPTR: bool = true;
    fn dataptr(x: crate::SEXP, writable: bool) -> *mut ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2).cast_mut();
            }
        }
        let direct =
            if writable {
                let d =
                    unsafe {
                        <[crate::Rcomplex; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[crate::Rcomplex; N] as
                            crate::altrep_data::AltrepDataptr<crate::Rcomplex>>::dataptr(d,
                        true).map(|p| p.cast::<::core::ffi::c_void>())
            } else {
                let ro =
                    {
                        let d =
                            unsafe {
                                <[crate::Rcomplex; N] as
                                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
                            };
                        <[crate::Rcomplex; N] as
                                crate::altrep_data::AltrepDataptr<crate::Rcomplex>>::dataptr_or_null(d)
                    };
                if let ::core::option::Option::Some(p) = ro {
                    return p.cast_mut().cast::<::core::ffi::c_void>();
                }
                let d =
                    unsafe {
                        <[crate::Rcomplex; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[crate::Rcomplex; N] as
                            crate::altrep_data::AltrepDataptr<crate::Rcomplex>>::dataptr(d,
                        false).map(|p| p.cast::<::core::ffi::c_void>())
            };
        if let ::core::option::Option::Some(p) = direct { return p; }
        unsafe {
            crate::altrep_data::materialize_altrep_data2::<crate::Rcomplex>(x)
        }
    }
    const HAS_DATAPTR_OR_NULL: bool = true;
    fn dataptr_or_null(x: crate::SEXP) -> *const ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2);
            }
        }
        let d =
            unsafe {
                <[crate::Rcomplex; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[crate::Rcomplex; N] as
                        crate::altrep_data::AltrepDataptr<crate::Rcomplex>>::dataptr_or_null(d).map(|p|
                    p.cast::<::core::ffi::c_void>()).unwrap_or(::core::ptr::null())
    }
}
impl<const N : usize> crate::altrep_traits::AltComplex for
    [crate::Rcomplex; N] where  {
    const HAS_ELT: bool = true;
    fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> crate::Rcomplex {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return <crate::Rcomplex as
                        crate::RNativeType>::elt(data2, i.max(0));
        }
        let data =
            unsafe {
                <[crate::Rcomplex; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[crate::Rcomplex; N] as
                crate::altrep_data::AltComplexData>::elt(data,
            i.max(0) as usize)
    }
    const HAS_GET_REGION: bool = true;
    fn get_region(x: crate::SEXP, start: crate::R_xlen_t,
        len: crate::R_xlen_t, buf: &mut [crate::Rcomplex])
        -> crate::R_xlen_t {
        if start < 0 || len <= 0 { return 0; }
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return unsafe {
                        crate::altrep_data::materialized_altrep_region::<crate::Rcomplex>(data2,
                            start as usize, len as usize, buf)
                    } as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[crate::Rcomplex; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let len = len as usize;
        <[crate::Rcomplex; N] as
                    crate::altrep_data::AltComplexData>::get_region(data,
                start as usize, len, buf) as crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_data::InferBase for [crate::Rcomplex; N]
    where  {
    const BASE: crate::altrep::RBase = crate::altrep::RBase::Complex;
    unsafe fn make_class(class_name: *const ::core::ffi::c_char,
        pkg_name: *const ::core::ffi::c_char)
        -> crate::sys::altrep::R_altrep_class_t {
        let dll = crate::altrep_dll_info();
        let cls =
            unsafe {
                crate::sys::altrep::R_make_altcomplex_class(class_name,
                    pkg_name, dll)
            };
        let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
        crate::altrep::validate_altrep_class(cls, name,
            crate::altrep::RBase::Complex)
    }
    unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
        unsafe {
            crate::altrep_bridge::install_base::<[crate::Rcomplex; N]>(cls)
        };
        unsafe {
            crate::altrep_bridge::install_vec::<[crate::Rcomplex; N]>(cls)
        };
        unsafe {
            crate::altrep_bridge::install_cplx::<[crate::Rcomplex; N]>(cls)
        };
    }
}crate::impl_altcomplex_from_data_generic!({const N: usize} [crate::Rcomplex; N] {}, dataptr);
16impl<const N : usize> crate::altrep_traits::Altrep for [crate::RLogical; N]
    where  {
    const GUARD: crate::altrep_traits::AltrepGuard =
        crate::altrep_traits::AltrepGuard::RUnwind;
    fn length(x: crate::SEXP) -> crate::R_xlen_t {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return crate::SexpExt::len(&data2) as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[crate::RLogical; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[crate::RLogical; N] as
                    crate::altrep_data::AltrepLen>::altrep_len(data) as
            crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_traits::AltVec for [crate::RLogical; N]
    where  {
    const HAS_DATAPTR: bool = true;
    fn dataptr(x: crate::SEXP, writable: bool) -> *mut ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2).cast_mut();
            }
        }
        let direct =
            if writable {
                let d =
                    unsafe {
                        <[crate::RLogical; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[crate::RLogical; N] as
                            crate::altrep_data::AltrepDataptr<i32>>::dataptr(d,
                        true).map(|p| p.cast::<::core::ffi::c_void>())
            } else {
                let ro =
                    {
                        let d =
                            unsafe {
                                <[crate::RLogical; N] as
                                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
                            };
                        <[crate::RLogical; N] as
                                crate::altrep_data::AltrepDataptr<i32>>::dataptr_or_null(d)
                    };
                if let ::core::option::Option::Some(p) = ro {
                    return p.cast_mut().cast::<::core::ffi::c_void>();
                }
                let d =
                    unsafe {
                        <[crate::RLogical; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[crate::RLogical; N] as
                            crate::altrep_data::AltrepDataptr<i32>>::dataptr(d,
                        false).map(|p| p.cast::<::core::ffi::c_void>())
            };
        if let ::core::option::Option::Some(p) = direct { return p; }
        unsafe { crate::altrep_data::materialize_altrep_data2::<i32>(x) }
    }
    const HAS_DATAPTR_OR_NULL: bool = true;
    fn dataptr_or_null(x: crate::SEXP) -> *const ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2);
            }
        }
        let d =
            unsafe {
                <[crate::RLogical; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[crate::RLogical; N] as
                        crate::altrep_data::AltrepDataptr<i32>>::dataptr_or_null(d).map(|p|
                    p.cast::<::core::ffi::c_void>()).unwrap_or(::core::ptr::null())
    }
}
impl<const N : usize> crate::altrep_traits::AltLogical for
    [crate::RLogical; N] where  {
    const HAS_ELT: bool = true;
    fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> i32 {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return <crate::RLogical as
                            crate::RNativeType>::elt(data2, i.max(0)).to_i32();
        }
        let data =
            unsafe {
                <[crate::RLogical; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let i = i.max(0) as usize;
        if let ::core::option::Option::Some(values) =
                <[crate::RLogical; N] as
                        crate::altrep_data::AltLogicalData>::as_r_slice(data) {
            return values[i];
        }
        <[crate::RLogical; N] as
                    crate::altrep_data::AltLogicalData>::elt(data, i).to_r_int()
    }
    const HAS_GET_REGION: bool = true;
    fn get_region(x: crate::SEXP, start: crate::R_xlen_t,
        len: crate::R_xlen_t, buf: &mut [i32]) -> crate::R_xlen_t {
        if start < 0 || len <= 0 { return 0; }
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return unsafe {
                        crate::altrep_data::materialized_altrep_region::<i32>(data2,
                            start as usize, len as usize, buf)
                    } as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[crate::RLogical; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let len = len as usize;
        <[crate::RLogical; N] as
                    crate::altrep_data::AltLogicalData>::get_region(data,
                start as usize, len, buf) as crate::R_xlen_t
    }
    const HAS_IS_SORTED: bool = true;
    fn is_sorted(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::altrep_traits::UNKNOWN_SORTEDNESS;
        }
        let data =
            unsafe {
                <[crate::RLogical; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[crate::RLogical; N] as
                        crate::altrep_data::AltLogicalData>::is_sorted(data).map(|s|
                    s.to_r_int()).unwrap_or(i32::MIN)
    }
    const HAS_NO_NA: bool = true;
    fn no_na(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return 0;
        }
        let data =
            unsafe {
                <[crate::RLogical; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[crate::RLogical; N] as
                        crate::altrep_data::AltLogicalData>::no_na(data).map(|b|
                    if b { 1 } else { 0 }).unwrap_or(0)
    }
    const HAS_SUM: bool = true;
    fn sum(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[crate::RLogical; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        match <[crate::RLogical; N] as
                    crate::altrep_data::AltLogicalData>::sum(data, narm) {
            ::core::option::Option::Some(s) => {
                if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
                    crate::SEXP::scalar_integer(s as i32)
                } else { crate::SEXP::scalar_real(s as f64) }
            }
            ::core::option::Option::None => crate::SEXP::null(),
        }
    }
}
impl<const N : usize> crate::altrep_data::InferBase for [crate::RLogical; N]
    where  {
    const BASE: crate::altrep::RBase = crate::altrep::RBase::Logical;
    unsafe fn make_class(class_name: *const ::core::ffi::c_char,
        pkg_name: *const ::core::ffi::c_char)
        -> crate::sys::altrep::R_altrep_class_t {
        let dll = crate::altrep_dll_info();
        let cls =
            unsafe {
                crate::sys::altrep::R_make_altlogical_class(class_name,
                    pkg_name, dll)
            };
        let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
        crate::altrep::validate_altrep_class(cls, name,
            crate::altrep::RBase::Logical)
    }
    unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
        unsafe {
            crate::altrep_bridge::install_base::<[crate::RLogical; N]>(cls)
        };
        unsafe {
            crate::altrep_bridge::install_vec::<[crate::RLogical; N]>(cls)
        };
        unsafe {
            crate::altrep_bridge::install_lgl::<[crate::RLogical; N]>(cls)
        };
    }
}crate::impl_altlogical_from_data_generic!({const N: usize} [crate::RLogical; N] {}, dataptr);
17impl<const N : usize> crate::altrep_traits::Altrep for [bool; N] where  {
    const GUARD: crate::altrep_traits::AltrepGuard =
        crate::altrep_traits::AltrepGuard::RUnwind;
    fn length(x: crate::SEXP) -> crate::R_xlen_t {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return crate::SexpExt::len(&data2) as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[bool; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[bool; N] as crate::altrep_data::AltrepLen>::altrep_len(data) as
            crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_data::AltrepDataptr<crate::RLogical> for
    [bool; N] where  {
    fn dataptr(&mut self, _writable: bool)
        -> ::core::option::Option<*mut crate::RLogical> {
        ::core::option::Option::None
    }
}
impl<const N : usize> crate::altrep_traits::AltVec for [bool; N] where  {
    const HAS_DATAPTR: bool = true;
    fn dataptr(x: crate::SEXP, writable: bool) -> *mut ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2).cast_mut();
            }
        }
        let direct =
            if writable {
                let d =
                    unsafe {
                        <[bool; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[bool; N] as
                            crate::altrep_data::AltrepDataptr<crate::RLogical>>::dataptr(d,
                        true).map(|p| p.cast::<::core::ffi::c_void>())
            } else {
                let ro =
                    {
                        let d =
                            unsafe {
                                <[bool; N] as
                                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
                            };
                        <[bool; N] as
                                crate::altrep_data::AltrepDataptr<crate::RLogical>>::dataptr_or_null(d)
                    };
                if let ::core::option::Option::Some(p) = ro {
                    return p.cast_mut().cast::<::core::ffi::c_void>();
                }
                let d =
                    unsafe {
                        <[bool; N] as
                                crate::altrep_data::AltrepExtract>::altrep_extract_mut(x)
                    };
                <[bool; N] as
                            crate::altrep_data::AltrepDataptr<crate::RLogical>>::dataptr(d,
                        false).map(|p| p.cast::<::core::ffi::c_void>())
            };
        if let ::core::option::Option::Some(p) = direct { return p; }
        unsafe {
            crate::altrep_data::materialize_altrep_data2::<crate::RLogical>(x)
        }
    }
    const HAS_DATAPTR_OR_NULL: bool = true;
    fn dataptr_or_null(x: crate::SEXP) -> *const ::core::ffi::c_void {
        unsafe {
            if let ::core::option::Option::Some(data2) =
                    crate::altrep_data::materialized_altrep_data2(x) {
                return crate::sys::DATAPTR_RO(data2);
            }
        }
        let d =
            unsafe {
                <[bool; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[bool; N] as
                        crate::altrep_data::AltrepDataptr<crate::RLogical>>::dataptr_or_null(d).map(|p|
                    p.cast::<::core::ffi::c_void>()).unwrap_or(::core::ptr::null())
    }
}
impl<const N : usize> crate::altrep_traits::AltLogical for [bool; N] where  {
    const HAS_ELT: bool = true;
    fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> i32 {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return <crate::RLogical as
                            crate::RNativeType>::elt(data2, i.max(0)).to_i32();
        }
        let data =
            unsafe {
                <[bool; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let i = i.max(0) as usize;
        if let ::core::option::Option::Some(values) =
                <[bool; N] as
                        crate::altrep_data::AltLogicalData>::as_r_slice(data) {
            return values[i];
        }
        <[bool; N] as
                    crate::altrep_data::AltLogicalData>::elt(data, i).to_r_int()
    }
    const HAS_GET_REGION: bool = true;
    fn get_region(x: crate::SEXP, start: crate::R_xlen_t,
        len: crate::R_xlen_t, buf: &mut [i32]) -> crate::R_xlen_t {
        if start < 0 || len <= 0 { return 0; }
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return unsafe {
                        crate::altrep_data::materialized_altrep_region::<i32>(data2,
                            start as usize, len as usize, buf)
                    } as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[bool; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        let len = len as usize;
        <[bool; N] as
                    crate::altrep_data::AltLogicalData>::get_region(data,
                start as usize, len, buf) as crate::R_xlen_t
    }
    const HAS_IS_SORTED: bool = true;
    fn is_sorted(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::altrep_traits::UNKNOWN_SORTEDNESS;
        }
        let data =
            unsafe {
                <[bool; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[bool; N] as
                        crate::altrep_data::AltLogicalData>::is_sorted(data).map(|s|
                    s.to_r_int()).unwrap_or(i32::MIN)
    }
    const HAS_NO_NA: bool = true;
    fn no_na(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return 0;
        }
        let data =
            unsafe {
                <[bool; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[bool; N] as
                        crate::altrep_data::AltLogicalData>::no_na(data).map(|b|
                    if b { 1 } else { 0 }).unwrap_or(0)
    }
    const HAS_SUM: bool = true;
    fn sum(x: crate::SEXP, narm: bool) -> crate::SEXP {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::SEXP::null();
        }
        let data =
            unsafe {
                <[bool; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        match <[bool; N] as
                    crate::altrep_data::AltLogicalData>::sum(data, narm) {
            ::core::option::Option::Some(s) => {
                if s >= i32::MIN as i64 && s <= i32::MAX as i64 {
                    crate::SEXP::scalar_integer(s as i32)
                } else { crate::SEXP::scalar_real(s as f64) }
            }
            ::core::option::Option::None => crate::SEXP::null(),
        }
    }
}
impl<const N : usize> crate::altrep_data::InferBase for [bool; N] where  {
    const BASE: crate::altrep::RBase = crate::altrep::RBase::Logical;
    unsafe fn make_class(class_name: *const ::core::ffi::c_char,
        pkg_name: *const ::core::ffi::c_char)
        -> crate::sys::altrep::R_altrep_class_t {
        let dll = crate::altrep_dll_info();
        let cls =
            unsafe {
                crate::sys::altrep::R_make_altlogical_class(class_name,
                    pkg_name, dll)
            };
        let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
        crate::altrep::validate_altrep_class(cls, name,
            crate::altrep::RBase::Logical)
    }
    unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
        unsafe { crate::altrep_bridge::install_base::<[bool; N]>(cls) };
        unsafe { crate::altrep_bridge::install_vec::<[bool; N]>(cls) };
        unsafe { crate::altrep_bridge::install_lgl::<[bool; N]>(cls) };
    }
}crate::impl_altlogical_from_data_generic!({const N: usize} [bool; N] {});
18impl<const N : usize> crate::altrep_traits::Altrep for [String; N] where  {
    const GUARD: crate::altrep_traits::AltrepGuard =
        crate::altrep_traits::AltrepGuard::RUnwind;
    fn length(x: crate::SEXP) -> crate::R_xlen_t {
        if let ::core::option::Option::Some(data2) =
                unsafe { crate::altrep_data::materialized_altrep_data2(x) } {
            return crate::SexpExt::len(&data2) as crate::R_xlen_t;
        }
        let data =
            unsafe {
                <[String; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[String; N] as crate::altrep_data::AltrepLen>::altrep_len(data) as
            crate::R_xlen_t
    }
}
impl<const N : usize> crate::altrep_traits::AltVec for [String; N] where  {
    const HAS_DATAPTR: bool = true;
    fn dataptr(x: crate::SEXP, writable: bool) -> *mut ::core::ffi::c_void {
        unsafe {
            crate::altrep_impl::altstring_dataptr::<[String; N]>(x, writable)
        }
    }
    const HAS_DATAPTR_OR_NULL: bool = true;
    fn dataptr_or_null(x: crate::SEXP) -> *const ::core::ffi::c_void {
        let _ = x;
        ::core::ptr::null()
    }
}
impl<const N : usize> crate::altrep_traits::AltString for [String; N] where  {
    fn elt(x: crate::SEXP, i: crate::R_xlen_t) -> crate::SEXP {
        unsafe { crate::altrep_impl::altstring_elt::<[String; N]>(x, i) }
    }
    const HAS_SET_ELT: bool = true;
    fn set_elt(x: crate::SEXP, i: crate::R_xlen_t, v: crate::SEXP) {
        unsafe {
            crate::altrep_impl::altstring_set_elt::<[String; N]>(x, i, v)
        }
    }
    const HAS_IS_SORTED: bool = true;
    fn is_sorted(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return crate::altrep_traits::UNKNOWN_SORTEDNESS;
        }
        let data =
            unsafe {
                <[String; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[String; N] as
                        crate::altrep_data::AltStringData>::is_sorted(data).map(|s|
                    s.to_r_int()).unwrap_or(i32::MIN)
    }
    const HAS_NO_NA: bool = true;
    fn no_na(x: crate::SEXP) -> i32 {
        if unsafe { crate::altrep_data::altrep_values_written(x) } {
            return 0;
        }
        let data =
            unsafe {
                <[String; N] as
                        crate::altrep_data::AltrepExtract>::altrep_extract_ref(x)
            };
        <[String; N] as
                        crate::altrep_data::AltStringData>::no_na(data).map(|b|
                    if b { 1 } else { 0 }).unwrap_or(0)
    }
}
impl<const N : usize> crate::altrep_data::InferBase for [String; N] where  {
    const BASE: crate::altrep::RBase = crate::altrep::RBase::String;
    unsafe fn make_class(class_name: *const ::core::ffi::c_char,
        pkg_name: *const ::core::ffi::c_char)
        -> crate::sys::altrep::R_altrep_class_t {
        let dll = crate::altrep_dll_info();
        let cls =
            unsafe {
                crate::sys::altrep::R_make_altstring_class(class_name,
                    pkg_name, dll)
            };
        let name = unsafe { ::core::ffi::CStr::from_ptr(class_name) };
        crate::altrep::validate_altrep_class(cls, name,
            crate::altrep::RBase::String)
    }
    unsafe fn install_methods(cls: crate::sys::altrep::R_altrep_class_t) {
        unsafe { crate::altrep_bridge::install_base::<[String; N]>(cls) };
        unsafe { crate::altrep_bridge::install_vec::<[String; N]>(cls) };
        unsafe { crate::altrep_bridge::install_str::<[String; N]>(cls) };
    }
}crate::impl_altstring_from_data_generic!({const N: usize} [String; N] {});
19
20macro_rules! register_array_family {
21    ($elem:ty, $name:literal) => {
22        impl<const N: usize> crate::altrep::RegisterAltrep for [$elem; N] {
23            fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
24                use std::collections::BTreeMap;
25                use std::ffi::CString;
26                use std::sync::Mutex;
27
28                static CLASSES: Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
29                    Mutex::new(BTreeMap::new());
30
31                crate::worker::with_r_thread(|| {
32                    let cached = CLASSES
33                        .lock()
34                        .expect("array ALTREP class cache poisoned")
35                        .get(&N)
36                        .copied();
37                    if let Some(class) = cached {
38                        return class;
39                    }
40
41                    // R copies/interns these bytes. Do not hold the cache lock
42                    // across R allocation or callback installation.
43                    let name = CString::new(format!("{}_{}", $name, N))
44                        .expect("array class name contains no NUL");
45                    let class = unsafe {
46                        <Self as crate::altrep_data::InferBase>::make_class(
47                            name.as_ptr(),
48                            crate::AltrepPkgName::as_ptr(),
49                        )
50                    };
51                    unsafe {
52                        <Self as crate::altrep_data::InferBase>::install_methods(class);
53                    }
54                    CLASSES
55                        .lock()
56                        .expect("array ALTREP class cache poisoned")
57                        .insert(N, class);
58                    class
59                })
60            }
61        }
62    };
63}
64
65impl<const N : usize> crate::altrep::RegisterAltrep for [i32; N] {
    fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
        use std::collections::BTreeMap;
        use std::ffi::CString;
        use std::sync::Mutex;
        static CLASSES:
            Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
            Mutex::new(BTreeMap::new());
        crate::worker::with_r_thread(||
                {
                    let cached =
                        CLASSES.lock().expect("array ALTREP class cache poisoned").get(&N).copied();
                    if let Some(class) = cached { return class; }
                    let name =
                        CString::new(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}_{1}", "Array_i32",
                                                N))
                                    })).expect("array class name contains no NUL");
                    let class =
                        unsafe {
                            <Self as
                                    crate::altrep_data::InferBase>::make_class(name.as_ptr(),
                                crate::AltrepPkgName::as_ptr())
                        };
                    unsafe {
                        <Self as
                                crate::altrep_data::InferBase>::install_methods(class);
                    }
                    CLASSES.lock().expect("array ALTREP class cache poisoned").insert(N,
                        class);
                    class
                })
    }
}register_array_family!(i32, "Array_i32");
66impl<const N : usize> crate::altrep::RegisterAltrep for [f64; N] {
    fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
        use std::collections::BTreeMap;
        use std::ffi::CString;
        use std::sync::Mutex;
        static CLASSES:
            Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
            Mutex::new(BTreeMap::new());
        crate::worker::with_r_thread(||
                {
                    let cached =
                        CLASSES.lock().expect("array ALTREP class cache poisoned").get(&N).copied();
                    if let Some(class) = cached { return class; }
                    let name =
                        CString::new(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}_{1}", "Array_f64",
                                                N))
                                    })).expect("array class name contains no NUL");
                    let class =
                        unsafe {
                            <Self as
                                    crate::altrep_data::InferBase>::make_class(name.as_ptr(),
                                crate::AltrepPkgName::as_ptr())
                        };
                    unsafe {
                        <Self as
                                crate::altrep_data::InferBase>::install_methods(class);
                    }
                    CLASSES.lock().expect("array ALTREP class cache poisoned").insert(N,
                        class);
                    class
                })
    }
}register_array_family!(f64, "Array_f64");
67impl<const N : usize> crate::altrep::RegisterAltrep for [u8; N] {
    fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
        use std::collections::BTreeMap;
        use std::ffi::CString;
        use std::sync::Mutex;
        static CLASSES:
            Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
            Mutex::new(BTreeMap::new());
        crate::worker::with_r_thread(||
                {
                    let cached =
                        CLASSES.lock().expect("array ALTREP class cache poisoned").get(&N).copied();
                    if let Some(class) = cached { return class; }
                    let name =
                        CString::new(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}_{1}", "Array_u8", N))
                                    })).expect("array class name contains no NUL");
                    let class =
                        unsafe {
                            <Self as
                                    crate::altrep_data::InferBase>::make_class(name.as_ptr(),
                                crate::AltrepPkgName::as_ptr())
                        };
                    unsafe {
                        <Self as
                                crate::altrep_data::InferBase>::install_methods(class);
                    }
                    CLASSES.lock().expect("array ALTREP class cache poisoned").insert(N,
                        class);
                    class
                })
    }
}register_array_family!(u8, "Array_u8");
68impl<const N : usize> crate::altrep::RegisterAltrep for [crate::Rcomplex; N] {
    fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
        use std::collections::BTreeMap;
        use std::ffi::CString;
        use std::sync::Mutex;
        static CLASSES:
            Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
            Mutex::new(BTreeMap::new());
        crate::worker::with_r_thread(||
                {
                    let cached =
                        CLASSES.lock().expect("array ALTREP class cache poisoned").get(&N).copied();
                    if let Some(class) = cached { return class; }
                    let name =
                        CString::new(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}_{1}",
                                                "Array_Rcomplex", N))
                                    })).expect("array class name contains no NUL");
                    let class =
                        unsafe {
                            <Self as
                                    crate::altrep_data::InferBase>::make_class(name.as_ptr(),
                                crate::AltrepPkgName::as_ptr())
                        };
                    unsafe {
                        <Self as
                                crate::altrep_data::InferBase>::install_methods(class);
                    }
                    CLASSES.lock().expect("array ALTREP class cache poisoned").insert(N,
                        class);
                    class
                })
    }
}register_array_family!(crate::Rcomplex, "Array_Rcomplex");
69impl<const N : usize> crate::altrep::RegisterAltrep for [crate::RLogical; N] {
    fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
        use std::collections::BTreeMap;
        use std::ffi::CString;
        use std::sync::Mutex;
        static CLASSES:
            Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
            Mutex::new(BTreeMap::new());
        crate::worker::with_r_thread(||
                {
                    let cached =
                        CLASSES.lock().expect("array ALTREP class cache poisoned").get(&N).copied();
                    if let Some(class) = cached { return class; }
                    let name =
                        CString::new(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}_{1}",
                                                "Array_RLogical", N))
                                    })).expect("array class name contains no NUL");
                    let class =
                        unsafe {
                            <Self as
                                    crate::altrep_data::InferBase>::make_class(name.as_ptr(),
                                crate::AltrepPkgName::as_ptr())
                        };
                    unsafe {
                        <Self as
                                crate::altrep_data::InferBase>::install_methods(class);
                    }
                    CLASSES.lock().expect("array ALTREP class cache poisoned").insert(N,
                        class);
                    class
                })
    }
}register_array_family!(crate::RLogical, "Array_RLogical");
70impl<const N : usize> crate::altrep::RegisterAltrep for [bool; N] {
    fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
        use std::collections::BTreeMap;
        use std::ffi::CString;
        use std::sync::Mutex;
        static CLASSES:
            Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
            Mutex::new(BTreeMap::new());
        crate::worker::with_r_thread(||
                {
                    let cached =
                        CLASSES.lock().expect("array ALTREP class cache poisoned").get(&N).copied();
                    if let Some(class) = cached { return class; }
                    let name =
                        CString::new(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}_{1}", "Array_bool",
                                                N))
                                    })).expect("array class name contains no NUL");
                    let class =
                        unsafe {
                            <Self as
                                    crate::altrep_data::InferBase>::make_class(name.as_ptr(),
                                crate::AltrepPkgName::as_ptr())
                        };
                    unsafe {
                        <Self as
                                crate::altrep_data::InferBase>::install_methods(class);
                    }
                    CLASSES.lock().expect("array ALTREP class cache poisoned").insert(N,
                        class);
                    class
                })
    }
}register_array_family!(bool, "Array_bool");
71impl<const N : usize> crate::altrep::RegisterAltrep for [String; N] {
    fn get_or_init_class() -> crate::sys::altrep::R_altrep_class_t {
        use std::collections::BTreeMap;
        use std::ffi::CString;
        use std::sync::Mutex;
        static CLASSES:
            Mutex<BTreeMap<usize, crate::sys::altrep::R_altrep_class_t>> =
            Mutex::new(BTreeMap::new());
        crate::worker::with_r_thread(||
                {
                    let cached =
                        CLASSES.lock().expect("array ALTREP class cache poisoned").get(&N).copied();
                    if let Some(class) = cached { return class; }
                    let name =
                        CString::new(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}_{1}", "Array_String",
                                                N))
                                    })).expect("array class name contains no NUL");
                    let class =
                        unsafe {
                            <Self as
                                    crate::altrep_data::InferBase>::make_class(name.as_ptr(),
                                crate::AltrepPkgName::as_ptr())
                        };
                    unsafe {
                        <Self as
                                crate::altrep_data::InferBase>::install_methods(class);
                    }
                    CLASSES.lock().expect("array ALTREP class cache poisoned").insert(N,
                        class);
                    class
                })
    }
}register_array_family!(String, "Array_String");