miniextendr_api/altrep_data/iter/
coerce.rs1use super::IterState;
13use super::macros::define_iter_data;
14use crate::altrep_data::{AltComplexData, AltIntegerData, AltRealData, AltStringData, AltrepLen};
15
16pub struct IterIntCoerceData<I, T>
34where
35 I: Iterator<Item = T>,
36 T: crate::coerce::Coerce<i32> + Copy,
37{
38 state: IterState<I, T>,
39}
40
41impl<I, T> IterIntCoerceData<I, T>
42where
43 I: Iterator<Item = T>,
44 T: crate::coerce::Coerce<i32> + Copy,
45{
46 pub fn from_iter(iter: I, len: usize) -> Self {
48 Self {
49 state: IterState::new(iter, len),
50 }
51 }
52}
53
54impl<I, T> IterIntCoerceData<I, T>
55where
56 I: ExactSizeIterator<Item = T>,
57 T: crate::coerce::Coerce<i32> + Copy,
58{
59 pub fn from_exact_iter(iter: I) -> Self {
61 Self {
62 state: IterState::from_exact_size(iter),
63 }
64 }
65}
66
67impl<I, T> AltrepLen for IterIntCoerceData<I, T>
68where
69 I: Iterator<Item = T>,
70 T: crate::coerce::Coerce<i32> + Copy,
71{
72 fn altrep_len(&self) -> usize {
73 self.state.len()
74 }
75}
76
77impl<I, T> AltIntegerData for IterIntCoerceData<I, T>
78where
79 I: Iterator<Item = T>,
80 T: crate::coerce::Coerce<i32> + Copy,
81{
82 fn elt(&self, i: usize) -> i32 {
83 self.state
84 .get_element(i)
85 .map(|val| val.coerce())
86 .unwrap_or(crate::altrep_traits::NA_INTEGER)
87 }
88}
89
90pub struct IterRealCoerceData<I, T>
105where
106 I: Iterator<Item = T>,
107 T: crate::coerce::Coerce<f64> + Copy,
108{
109 state: IterState<I, T>,
110}
111
112impl<I, T> IterRealCoerceData<I, T>
113where
114 I: Iterator<Item = T>,
115 T: crate::coerce::Coerce<f64> + Copy,
116{
117 pub fn from_iter(iter: I, len: usize) -> Self {
119 Self {
120 state: IterState::new(iter, len),
121 }
122 }
123}
124
125impl<I, T> IterRealCoerceData<I, T>
126where
127 I: ExactSizeIterator<Item = T>,
128 T: crate::coerce::Coerce<f64> + Copy,
129{
130 pub fn from_exact_iter(iter: I) -> Self {
132 Self {
133 state: IterState::from_exact_size(iter),
134 }
135 }
136}
137
138impl<I, T> AltrepLen for IterRealCoerceData<I, T>
139where
140 I: Iterator<Item = T>,
141 T: crate::coerce::Coerce<f64> + Copy,
142{
143 fn altrep_len(&self) -> usize {
144 self.state.len()
145 }
146}
147
148impl<I, T> AltRealData for IterRealCoerceData<I, T>
149where
150 I: Iterator<Item = T>,
151 T: crate::coerce::Coerce<f64> + Copy,
152{
153 fn elt(&self, i: usize) -> f64 {
154 self.state
155 .get_element(i)
156 .map(|val| val.coerce())
157 .unwrap_or(crate::altrep_traits::NA_REAL)
158 }
159}
160
161#[doc =
r" Iterator-backed integer vector data adaptor with coercion from bool."]
#[doc = r""]
#[doc = r" Wraps an iterator producing `bool` values that coerce to `i32`."]
#[doc = r" Useful for converting boolean iterators to integer vectors."]
pub struct IterIntFromBoolData<I: Iterator<Item = bool>> {
state: super::IterState<I, bool>,
}
#[automatically_derived]
impl<I: ::core::clone::Clone + Iterator<Item = bool>> ::core::clone::Clone for
IterIntFromBoolData<I> {
#[inline]
fn clone(&self) -> Self {
IterIntFromBoolData {
state: ::core::clone::Clone::clone(&self.state),
}
}
}
impl<I: Iterator<Item = bool>> IterIntFromBoolData<I> {
pub fn from_iter(iter: I, len: usize) -> Self {
Self { state: super::IterState::new(iter, len) }
}
}
impl<I: Iterator<Item = bool>> crate::altrep_data::AltrepSerialize for
IterIntFromBoolData<I> {
fn serialized_state(&self) -> crate::SEXP {
match self.state.try_materialize_all() {
Ok(values) => crate::IntoR::into_sexp(values.to_vec()),
Err(_) => crate::SEXP::null(),
}
}
fn unserialize(state: crate::SEXP) -> Option<Self> {
let values =
<Vec<bool> as crate::TryFromSexp>::try_from_sexp(state).ok()?;
Some(Self { state: super::IterState::from_values(values) })
}
}
impl<I: ExactSizeIterator<Item = bool>> IterIntFromBoolData<I> {
pub fn from_exact_iter(iter: I) -> Self {
let len = iter.len();
Self::from_iter(iter, len)
}
}
impl<I: Iterator<Item = bool>> crate::altrep_data::AltrepLen for
IterIntFromBoolData<I> {
fn altrep_len(&self) -> usize { self.state.len() }
}define_iter_data! {
162IterIntFromBoolData, bool
167}
168
169impl<I> AltIntegerData for IterIntFromBoolData<I>
170where
171 I: Iterator<Item = bool>,
172{
173 fn elt(&self, i: usize) -> i32 {
174 use crate::coerce::Coerce;
175 self.state
176 .get_element(i)
177 .map(|val| val.coerce())
178 .unwrap_or(crate::altrep_traits::NA_INTEGER)
179 }
180}
181
182#[doc = r" Iterator-backed string vector data adaptor."]
#[doc = r""]
#[doc =
r" Wraps an iterator producing `String` values and implements the data-level"]
#[doc =
r" traits ([`AltrepLen`] + [`AltStringData`]) for backing an ALTREP character"]
#[doc =
r" vector. To expose it to R, wrap it in a `#[derive(AltrepString)]` +"]
#[doc =
r" `#[altrep(manual)]` struct (see the iterator module documentation)."]
#[doc = r""]
#[doc = r" # Performance Warning"]
#[doc = r""]
#[doc =
r" Unlike other `Iter*Data` types, **accessing ANY element forces full materialization"]
#[doc =
r" of the entire iterator**. This is because R's `AltStringData::elt()` returns a borrowed"]
#[doc =
r" `&str`, which requires stable storage. The internal `RefCell` cannot provide the required"]
#[doc = r" lifetime, so all strings must be materialized upfront."]
#[doc = r""]
#[doc = r" This means:"]
#[doc =
r" - `elt(0)` on a million-element iterator will generate ALL million strings"]
#[doc = r" - There is no lazy evaluation benefit for string iterators"]
#[doc =
r" - Memory usage equals the full vector regardless of access patterns"]
#[doc = r""]
#[doc =
r" For truly lazy string ALTREP, consider implementing a custom type that stores"]
#[doc =
r" strings in a way that allows borrowing without full materialization (e.g., arena"]
#[doc = r" allocation or caching generated strings incrementally)."]
#[doc = r""]
#[doc = r" # Example"]
#[doc = r""]
#[doc = r" ```ignore"]
#[doc = r" use miniextendr_api::altrep_data::IterStringData;"]
#[doc = r""]
#[doc = r#" let iter = (0..5).map(|x| format!("item_{}", x));"#]
#[doc = r" let data = IterStringData::from_iter(iter, 5);"]
#[doc = r" // First access to ANY element will materialize all 5 strings"]
#[doc = r" ```"]
pub struct IterStringData<I: Iterator<Item = String>> {
state: super::IterState<I, String>,
}
#[automatically_derived]
impl<I: ::core::clone::Clone + Iterator<Item = String>> ::core::clone::Clone
for IterStringData<I> {
#[inline]
fn clone(&self) -> Self {
IterStringData { state: ::core::clone::Clone::clone(&self.state) }
}
}
impl<I: Iterator<Item = String>> IterStringData<I> {
pub fn from_iter(iter: I, len: usize) -> Self {
Self { state: super::IterState::new(iter, len) }
}
}
impl<I: Iterator<Item = String>> crate::altrep_data::AltrepSerialize for
IterStringData<I> {
fn serialized_state(&self) -> crate::SEXP {
match self.state.try_materialize_all() {
Ok(values) => crate::IntoR::into_sexp(values.to_vec()),
Err(_) => crate::SEXP::null(),
}
}
fn unserialize(state: crate::SEXP) -> Option<Self> {
let values =
<Vec<String> as crate::TryFromSexp>::try_from_sexp(state).ok()?;
Some(Self { state: super::IterState::from_values(values) })
}
}
impl<I: ExactSizeIterator<Item = String>> IterStringData<I> {
pub fn from_exact_iter(iter: I) -> Self {
let len = iter.len();
Self::from_iter(iter, len)
}
}
impl<I: Iterator<Item = String>> crate::altrep_data::AltrepLen for
IterStringData<I> {
fn altrep_len(&self) -> usize { self.state.len() }
}define_iter_data! {
183IterStringData, String
216}
217
218impl<I> AltStringData for IterStringData<I>
219where
220 I: Iterator<Item = String>,
221{
222 fn elt(&self, i: usize) -> Option<&str> {
223 let materialized = self.state.materialize_all();
226 materialized.get(i).map(|s| s.as_str())
227 }
228}
229
230#[doc = r" Iterator-backed complex number vector data adaptor."]
#[doc = r""]
#[doc =
r" Wraps an iterator producing `Rcomplex` values and implements the data-level"]
#[doc =
r" traits ([`AltrepLen`] + [`AltComplexData`]) for backing an ALTREP complex"]
#[doc =
r" vector. To expose it to R, wrap it in a `#[derive(AltrepComplex)]` +"]
#[doc =
r" `#[altrep(manual)]` struct (see the iterator module documentation)."]
#[doc = r""]
#[doc = r" # Example"]
#[doc = r""]
#[doc = r" ```ignore"]
#[doc = r" use miniextendr_api::altrep_data::IterComplexData;"]
#[doc = r" use miniextendr_api::Rcomplex;"]
#[doc = r""]
#[doc =
r" let iter = (0..5).map(|x| Rcomplex { r: x as f64, i: (x * 2) as f64 });"]
#[doc = r" let data = IterComplexData::from_iter(iter, 5);"]
#[doc = r" ```"]
pub struct IterComplexData<I: Iterator<Item = crate::Rcomplex>> {
state: super::IterState<I, crate::Rcomplex>,
}
#[automatically_derived]
impl<I: ::core::clone::Clone + Iterator<Item = crate::Rcomplex>>
::core::clone::Clone for IterComplexData<I> {
#[inline]
fn clone(&self) -> Self {
IterComplexData { state: ::core::clone::Clone::clone(&self.state) }
}
}
impl<I: Iterator<Item = crate::Rcomplex>> IterComplexData<I> {
pub fn from_iter(iter: I, len: usize) -> Self {
Self { state: super::IterState::new(iter, len) }
}
}
impl<I: Iterator<Item = crate::Rcomplex>> crate::altrep_data::AltrepSerialize
for IterComplexData<I> {
fn serialized_state(&self) -> crate::SEXP {
match self.state.try_materialize_all() {
Ok(values) => crate::IntoR::into_sexp(values.to_vec()),
Err(_) => crate::SEXP::null(),
}
}
fn unserialize(state: crate::SEXP) -> Option<Self> {
let values =
<Vec<crate::Rcomplex> as
crate::TryFromSexp>::try_from_sexp(state).ok()?;
Some(Self { state: super::IterState::from_values(values) })
}
}
impl<I: ExactSizeIterator<Item = crate::Rcomplex>> IterComplexData<I> {
pub fn from_exact_iter(iter: I) -> Self {
let len = iter.len();
Self::from_iter(iter, len)
}
}
impl<I: Iterator<Item = crate::Rcomplex>> crate::altrep_data::AltrepLen for
IterComplexData<I> {
fn altrep_len(&self) -> usize { self.state.len() }
}define_iter_data! {
231IterComplexData, crate::Rcomplex
248}
249
250impl<I> AltComplexData for IterComplexData<I>
251where
252 I: Iterator<Item = crate::Rcomplex>,
253{
254 fn elt(&self, i: usize) -> crate::Rcomplex {
255 self.state
256 .get_element(i)
257 .unwrap_or(<crate::Rcomplex as crate::RNativeType>::R_NA)
258 }
259
260 fn as_slice(&self) -> Option<&[crate::Rcomplex]> {
261 self.state.as_materialized()
262 }
263}