Skip to main content

miniextendr_api/altrep_data/iter/
extension.rs

1//! Iterator capability-based construction; no per-adapter implementations.
2
3use super::{
4    IterComplexData, IterIntData, IterLogicalData, IterRLogicalData, IterRawData, IterRealData,
5    IterStringData,
6};
7use crate::altrep_data::AltrepLen;
8
9/// Choose the ALTREP data family for an iterator's element type.
10///
11/// Built-in mappings cover native numeric values, logicals and owned strings.
12/// A local element type may implement this trait to select its own data adapter
13/// (for example, an existing coercing adapter). The resulting data still needs
14/// a concrete registered class, which owns duplication and serialization policy.
15///
16/// Raw SEXP is deliberately not inferred: storing one requires a GC-root owner.
17pub trait AltrepIteratorItem: Sized {
18    /// Data adapter retaining the concrete iterator type.
19    type Data<I: Iterator<Item = Self>>: AltrepLen;
20
21    /// Store the iterator without advancing it.
22    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize) -> Self::Data<I>;
23}
24
25/// ALTREP data constructors for every iterator, including third-party adapters.
26///
27/// Exact-size iterators can supply their remaining length. Other iterators need
28/// an explicit finite prefix length; neither constructor counts or collects them.
29/// Borrowed iterators can be used as data adapters, but an R-owned class must own
30/// its source for the whole R lifetime.
31///
32/// The item type picks the data family, so an unsuffixed integer literal can't
33/// fall back to `i32` here: write `0..6i32`, not `0..6`.
34///
35/// ```
36/// use miniextendr_api::{AltrepIteratorExt, AltIntegerData, AltrepLen};
37/// let data = (0..6i32).map(|x| x * 2).into_altrep_data_exact();
38/// assert_eq!(data.altrep_len(), 6);
39/// assert_eq!(data.elt(2), 4);
40/// ```
41pub trait AltrepIteratorExt: Iterator + Sized {
42    /// Cache a finite prefix in the item's chosen ALTREP data family.
43    fn into_altrep_data(self, len: usize) -> <Self::Item as AltrepIteratorItem>::Data<Self>
44    where
45        Self::Item: AltrepIteratorItem,
46    {
47        Self::Item::into_data(self, len)
48    }
49
50    /// Use the iterator's exact remaining length without advancing it.
51    fn into_altrep_data_exact(self) -> <Self::Item as AltrepIteratorItem>::Data<Self>
52    where
53        Self: ExactSizeIterator,
54        Self::Item: AltrepIteratorItem,
55    {
56        let len = self.len();
57        self.into_altrep_data(len)
58    }
59}
60
61impl<I: Iterator> AltrepIteratorExt for I {}
62
63macro_rules! iterator_item {
64    ($item:ty => $data:ident) => {
65        impl AltrepIteratorItem for $item {
66            type Data<I: Iterator<Item = Self>> = $data<I>;
67
68            fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize) -> Self::Data<I> {
69                $data::from_iter(iter, len)
70            }
71        }
72    };
73}
74
75impl AltrepIteratorItem for i32 {
    type Data<I: Iterator<Item = Self>> = IterIntData<I>;
    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize)
        -> Self::Data<I> {
        IterIntData::from_iter(iter, len)
    }
}iterator_item!(i32 => IterIntData);
76impl AltrepIteratorItem for f64 {
    type Data<I: Iterator<Item = Self>> = IterRealData<I>;
    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize)
        -> Self::Data<I> {
        IterRealData::from_iter(iter, len)
    }
}iterator_item!(f64 => IterRealData);
77impl AltrepIteratorItem for u8 {
    type Data<I: Iterator<Item = Self>> = IterRawData<I>;
    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize)
        -> Self::Data<I> {
        IterRawData::from_iter(iter, len)
    }
}iterator_item!(u8 => IterRawData);
78impl AltrepIteratorItem for crate::Rcomplex {
    type Data<I: Iterator<Item = Self>> = IterComplexData<I>;
    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize)
        -> Self::Data<I> {
        IterComplexData::from_iter(iter, len)
    }
}iterator_item!(crate::Rcomplex => IterComplexData);
79impl AltrepIteratorItem for crate::RLogical {
    type Data<I: Iterator<Item = Self>> = IterRLogicalData<I>;
    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize)
        -> Self::Data<I> {
        IterRLogicalData::from_iter(iter, len)
    }
}iterator_item!(crate::RLogical => IterRLogicalData);
80impl AltrepIteratorItem for bool {
    type Data<I: Iterator<Item = Self>> = IterLogicalData<I>;
    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize)
        -> Self::Data<I> {
        IterLogicalData::from_iter(iter, len)
    }
}iterator_item!(bool => IterLogicalData);
81impl AltrepIteratorItem for String {
    type Data<I: Iterator<Item = Self>> = IterStringData<I>;
    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize)
        -> Self::Data<I> {
        IterStringData::from_iter(iter, len)
    }
}iterator_item!(String => IterStringData);
82
83// IsNA excludes raw bytes: None must not silently become a real zero byte.
84impl<T: crate::IsNA + AltrepIteratorItem> AltrepIteratorItem for Option<T> {
85    type Data<I: Iterator<Item = Self>> = T::Data<std::iter::Map<I, fn(Option<T>) -> T>>;
86
87    fn into_data<I: Iterator<Item = Self>>(iter: I, len: usize) -> Self::Data<I> {
88        let native: fn(Option<T>) -> T = |value| value.unwrap_or(T::R_NA);
89        T::into_data(iter.map(native), len)
90    }
91}