miniextendr_api/altrep_data/iter/
sparse.rs1use std::cell::RefCell;
12use std::collections::BTreeMap;
13
14use crate::altrep_data::{
15 AltComplexData, AltIntegerData, AltLogicalData, AltRawData, AltRealData, AltrepLen, Logical,
16 fill_region,
17};
18
19pub struct SparseIterState<I, T> {
61 len: usize,
63 iter: RefCell<Option<(I, usize)>>,
65 cache: RefCell<BTreeMap<usize, T>>,
67}
68
69impl<I, T> SparseIterState<I, T>
70where
71 I: Iterator<Item = T>,
72{
73 pub fn new(iter: I, len: usize) -> Self {
84 Self {
85 len,
86 iter: RefCell::new((len != 0).then_some((iter, 0))),
87 cache: RefCell::new(BTreeMap::new()),
88 }
89 }
90
91 pub fn get_element(&self, i: usize) -> Option<T>
104 where
105 T: Copy,
106 {
107 if i >= self.len {
109 return None;
110 }
111
112 {
114 let cache = self.cache.borrow();
115 if let Some(&val) = cache.get(&i) {
116 return Some(val);
117 }
118 }
119
120 let mut iter_opt = self.iter.borrow_mut();
122 let (iter, pos) = iter_opt.as_mut()?;
123
124 if i < *pos {
126 return None;
127 }
128
129 let skip_count = i - *pos;
131 let elem = match iter.nth(skip_count) {
132 Some(elem) => elem,
133 None => {
134 iter_opt.take();
137 return None;
138 }
139 };
140 *pos = i + 1;
141 if *pos == self.len {
142 iter_opt.take();
143 }
144
145 drop(iter_opt);
147 self.cache.borrow_mut().insert(i, elem);
148
149 Some(elem)
150 }
151
152 pub fn iterator_position(&self) -> Option<usize> {
156 self.iter.borrow().as_ref().map(|(_, pos)| *pos)
157 }
158
159 pub fn is_cached(&self, i: usize) -> bool {
161 self.cache.borrow().contains_key(&i)
162 }
163
164 pub fn cached_count(&self) -> usize {
166 self.cache.borrow().len()
167 }
168
169 pub fn len(&self) -> usize {
171 self.len
172 }
173
174 pub fn is_empty(&self) -> bool {
176 self.len == 0
177 }
178}
179
180impl<I, T> SparseIterState<I, T>
181where
182 I: ExactSizeIterator<Item = T>,
183{
184 pub fn from_exact_size(iter: I) -> Self {
186 let len = iter.len();
187 Self::new(iter, len)
188 }
189}
190
191pub struct SparseIterIntData<I: Iterator<Item = i32>> {
206 state: SparseIterState<I, i32>,
207}
208
209impl<I: Iterator<Item = i32>> SparseIterIntData<I> {
210 pub fn from_iter(iter: I, len: usize) -> Self {
212 Self {
213 state: SparseIterState::new(iter, len),
214 }
215 }
216}
217
218impl<I: ExactSizeIterator<Item = i32>> SparseIterIntData<I> {
219 pub fn from_exact_iter(iter: I) -> Self {
221 Self {
222 state: SparseIterState::from_exact_size(iter),
223 }
224 }
225}
226
227impl<I: Iterator<Item = i32>> AltrepLen for SparseIterIntData<I> {
228 fn altrep_len(&self) -> usize {
229 self.state.len()
230 }
231}
232
233impl<I: Iterator<Item = i32>> AltIntegerData for SparseIterIntData<I> {
234 fn elt(&self, i: usize) -> i32 {
235 self.state
236 .get_element(i)
237 .unwrap_or(crate::altrep_traits::NA_INTEGER)
238 }
239
240 fn as_slice(&self) -> Option<&[i32]> {
241 None
243 }
244
245 fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
246 fill_region(start, len, self.altrep_len(), buf, |idx| self.elt(idx))
247 }
248}
249
250pub struct SparseIterRealData<I: Iterator<Item = f64>> {
255 state: SparseIterState<I, f64>,
256}
257
258impl<I: Iterator<Item = f64>> SparseIterRealData<I> {
259 pub fn from_iter(iter: I, len: usize) -> Self {
261 Self {
262 state: SparseIterState::new(iter, len),
263 }
264 }
265}
266
267impl<I: ExactSizeIterator<Item = f64>> SparseIterRealData<I> {
268 pub fn from_exact_iter(iter: I) -> Self {
270 Self {
271 state: SparseIterState::from_exact_size(iter),
272 }
273 }
274}
275
276impl<I: Iterator<Item = f64>> AltrepLen for SparseIterRealData<I> {
277 fn altrep_len(&self) -> usize {
278 self.state.len()
279 }
280}
281
282impl<I: Iterator<Item = f64>> AltRealData for SparseIterRealData<I> {
283 fn elt(&self, i: usize) -> f64 {
284 self.state
285 .get_element(i)
286 .unwrap_or(crate::altrep_traits::NA_REAL)
287 }
288
289 fn as_slice(&self) -> Option<&[f64]> {
290 None
291 }
292
293 fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
294 fill_region(start, len, self.altrep_len(), buf, |idx| self.elt(idx))
295 }
296}
297
298pub struct SparseIterLogicalData<I: Iterator<Item = bool>> {
300 state: SparseIterState<I, bool>,
301}
302
303impl<I: Iterator<Item = bool>> SparseIterLogicalData<I> {
304 pub fn from_iter(iter: I, len: usize) -> Self {
306 Self {
307 state: SparseIterState::new(iter, len),
308 }
309 }
310}
311
312impl<I: ExactSizeIterator<Item = bool>> SparseIterLogicalData<I> {
313 pub fn from_exact_iter(iter: I) -> Self {
315 Self {
316 state: SparseIterState::from_exact_size(iter),
317 }
318 }
319}
320
321impl<I: Iterator<Item = bool>> AltrepLen for SparseIterLogicalData<I> {
322 fn altrep_len(&self) -> usize {
323 self.state.len()
324 }
325}
326
327impl<I: Iterator<Item = bool>> AltLogicalData for SparseIterLogicalData<I> {
328 fn elt(&self, i: usize) -> Logical {
329 self.state
330 .get_element(i)
331 .map(Logical::from_bool)
332 .unwrap_or(Logical::Na)
333 }
334
335 fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
336 fill_region(start, len, self.altrep_len(), buf, |idx| {
337 self.elt(idx).to_r_int()
338 })
339 }
340}
341
342pub struct SparseIterRawData<I: Iterator<Item = u8>> {
344 state: SparseIterState<I, u8>,
345}
346
347impl<I: Iterator<Item = u8>> SparseIterRawData<I> {
348 pub fn from_iter(iter: I, len: usize) -> Self {
350 Self {
351 state: SparseIterState::new(iter, len),
352 }
353 }
354}
355
356impl<I: ExactSizeIterator<Item = u8>> SparseIterRawData<I> {
357 pub fn from_exact_iter(iter: I) -> Self {
359 Self {
360 state: SparseIterState::from_exact_size(iter),
361 }
362 }
363}
364
365impl<I: Iterator<Item = u8>> AltrepLen for SparseIterRawData<I> {
366 fn altrep_len(&self) -> usize {
367 self.state.len()
368 }
369}
370
371impl<I: Iterator<Item = u8>> AltRawData for SparseIterRawData<I> {
372 fn elt(&self, i: usize) -> u8 {
373 self.state.get_element(i).unwrap_or(0)
374 }
375
376 fn as_slice(&self) -> Option<&[u8]> {
377 None
378 }
379
380 fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
381 fill_region(start, len, self.altrep_len(), buf, |idx| self.elt(idx))
382 }
383}
384
385pub struct SparseIterComplexData<I>
387where
388 I: Iterator<Item = crate::Rcomplex>,
389{
390 state: SparseIterState<I, crate::Rcomplex>,
391}
392
393impl<I> SparseIterComplexData<I>
394where
395 I: Iterator<Item = crate::Rcomplex>,
396{
397 pub fn from_iter(iter: I, len: usize) -> Self {
399 Self {
400 state: SparseIterState::new(iter, len),
401 }
402 }
403}
404
405impl<I> SparseIterComplexData<I>
406where
407 I: ExactSizeIterator<Item = crate::Rcomplex>,
408{
409 pub fn from_exact_iter(iter: I) -> Self {
411 Self {
412 state: SparseIterState::from_exact_size(iter),
413 }
414 }
415}
416
417impl<I> AltrepLen for SparseIterComplexData<I>
418where
419 I: Iterator<Item = crate::Rcomplex>,
420{
421 fn altrep_len(&self) -> usize {
422 self.state.len()
423 }
424}
425
426impl<I> AltComplexData for SparseIterComplexData<I>
427where
428 I: Iterator<Item = crate::Rcomplex>,
429{
430 fn elt(&self, i: usize) -> crate::Rcomplex {
431 self.state
432 .get_element(i)
433 .unwrap_or(<crate::Rcomplex as crate::RNativeType>::R_NA)
434 }
435
436 fn as_slice(&self) -> Option<&[crate::Rcomplex]> {
437 None
438 }
439
440 fn get_region(&self, start: usize, len: usize, buf: &mut [crate::Rcomplex]) -> usize {
441 fill_region(start, len, self.altrep_len(), buf, |idx| self.elt(idx))
442 }
443}
444
445#[cfg(test)]
446mod tests {
447 use super::SparseIterState;
448 use std::cell::Cell;
449 use std::rc::Rc;
450
451 #[test]
452 fn exhausted_sparse_sources_never_resume() {
453 let polls = Cell::new(0);
455 let source = std::iter::from_fn(|| {
456 let poll = polls.get() + 1;
457 polls.set(poll);
458 match poll {
459 1 => Some(10),
460 3 => Some(20),
461 _ => None,
462 }
463 });
464 let state = SparseIterState::new(source, 4);
465 assert_eq!(state.get_element(0), Some(10));
466 assert_eq!(state.get_element(2), None); assert_eq!(state.iterator_position(), None);
468 assert_eq!(state.get_element(2), None);
469 assert_eq!(state.get_element(1), None);
470 assert_eq!(state.get_element(0), Some(10)); assert_eq!(polls.get(), 2);
472 }
473
474 #[test]
475 fn declared_prefix_drops_the_source_without_an_extra_poll() {
476 for len in [0, 3] {
477 let owner = Rc::new(());
479 let captured = Rc::clone(&owner);
480 let polls = Cell::new(0);
481 let poll_count = &polls;
482 let source = std::iter::from_fn(move || {
483 let _keep_alive = &captured;
484 let poll = poll_count.get();
485 assert!(poll < len, "read beyond the declared prefix");
486 poll_count.set(poll + 1);
487 Some(poll)
488 });
489 let state = SparseIterState::new(source, len);
490 if len != 0 {
491 assert_eq!(state.iterator_position(), Some(0));
492 assert_eq!(state.get_element(len - 1), Some(len - 1));
493 assert_eq!(state.get_element(0), None); assert_eq!(state.get_element(len - 1), Some(len - 1));
495 }
496 assert_eq!(state.iterator_position(), None);
497 assert_eq!(state.get_element(len), None);
498 assert_eq!(polls.get(), len);
499 assert_eq!(Rc::strong_count(&owner), 1);
500 }
501 }
502}