1use std::cell::RefCell;
7use std::collections::BTreeMap;
8
9use crate::altrep_data::{
10 AltComplexData, AltIntegerData, AltLogicalData, AltRawData, AltRealData, AltrepLen, InferBase,
11 Logical, fill_region,
12};
13
14pub struct SparseIterState<I, T> {
56 len: usize,
58 iter: RefCell<Option<(I, usize)>>,
60 cache: RefCell<BTreeMap<usize, T>>,
62}
63
64impl<I, T> SparseIterState<I, T>
65where
66 I: Iterator<Item = T>,
67{
68 pub fn new(iter: I, len: usize) -> Self {
75 Self {
76 len,
77 iter: RefCell::new(Some((iter, 0))),
78 cache: RefCell::new(BTreeMap::new()),
79 }
80 }
81
82 pub fn get_element(&self, i: usize) -> Option<T>
95 where
96 T: Copy,
97 {
98 if i >= self.len {
100 return None;
101 }
102
103 {
105 let cache = self.cache.borrow();
106 if let Some(&val) = cache.get(&i) {
107 return Some(val);
108 }
109 }
110
111 let mut iter_opt = self.iter.borrow_mut();
113 let (iter, pos) = iter_opt.as_mut()?;
114
115 if i < *pos {
117 return None;
118 }
119
120 let skip_count = i - *pos;
122 let elem = iter.nth(skip_count)?;
123 *pos = i + 1;
124
125 drop(iter_opt);
127 self.cache.borrow_mut().insert(i, elem);
128
129 Some(elem)
130 }
131
132 pub fn iterator_position(&self) -> Option<usize> {
136 self.iter.borrow().as_ref().map(|(_, pos)| *pos)
137 }
138
139 pub fn is_cached(&self, i: usize) -> bool {
141 self.cache.borrow().contains_key(&i)
142 }
143
144 pub fn cached_count(&self) -> usize {
146 self.cache.borrow().len()
147 }
148
149 pub fn len(&self) -> usize {
151 self.len
152 }
153
154 pub fn is_empty(&self) -> bool {
156 self.len == 0
157 }
158}
159
160impl<I, T> SparseIterState<I, T>
161where
162 I: ExactSizeIterator<Item = T>,
163{
164 pub fn from_exact_size(iter: I) -> Self {
166 let len = iter.len();
167 Self::new(iter, len)
168 }
169}
170
171pub struct SparseIterIntData<I: Iterator<Item = i32>> {
186 state: SparseIterState<I, i32>,
187}
188
189impl<I: Iterator<Item = i32>> SparseIterIntData<I> {
190 pub fn from_iter(iter: I, len: usize) -> Self {
192 Self {
193 state: SparseIterState::new(iter, len),
194 }
195 }
196}
197
198impl<I: ExactSizeIterator<Item = i32>> SparseIterIntData<I> {
199 pub fn from_exact_iter(iter: I) -> Self {
201 Self {
202 state: SparseIterState::from_exact_size(iter),
203 }
204 }
205}
206
207impl<I: Iterator<Item = i32>> AltrepLen for SparseIterIntData<I> {
208 fn len(&self) -> usize {
209 self.state.len()
210 }
211}
212
213impl<I: Iterator<Item = i32>> AltIntegerData for SparseIterIntData<I> {
214 fn elt(&self, i: usize) -> i32 {
215 self.state
216 .get_element(i)
217 .unwrap_or(crate::altrep_traits::NA_INTEGER)
218 }
219
220 fn as_slice(&self) -> Option<&[i32]> {
221 None
223 }
224
225 fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
226 fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
227 }
228}
229
230impl<I: Iterator<Item = i32> + 'static> crate::externalptr::TypedExternal for SparseIterIntData<I> {
231 const TYPE_NAME: &'static str = "SparseIterIntData";
232 const TYPE_NAME_CSTR: &'static [u8] = b"SparseIterIntData\0";
233 const TYPE_ID_CSTR: &'static [u8] = b"miniextendr_api::altrep::SparseIterIntData\0";
234}
235
236impl<I: Iterator<Item = i32> + 'static> InferBase for SparseIterIntData<I> {
237 const BASE: crate::altrep::RBase = crate::altrep::RBase::Int;
238
239 unsafe fn make_class(
240 class_name: *const i8,
241 pkg_name: *const i8,
242 ) -> crate::ffi::altrep::R_altrep_class_t {
243 unsafe {
244 crate::ffi::altrep::R_make_altinteger_class(class_name, pkg_name, core::ptr::null_mut())
245 }
246 }
247
248 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
249 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
250 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
251 unsafe { crate::altrep_bridge::install_int::<Self>(cls) };
252 }
253}
254
255impl<I: Iterator<Item = i32> + 'static> crate::altrep_traits::Altrep for SparseIterIntData<I> {
256 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
257 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
258 data.len() as crate::ffi::R_xlen_t
259 }
260}
261
262impl<I: Iterator<Item = i32> + 'static> crate::altrep_traits::AltVec for SparseIterIntData<I> {}
263
264impl<I: Iterator<Item = i32> + 'static> crate::altrep_traits::AltInteger for SparseIterIntData<I> {
265 const HAS_ELT: bool = true;
266
267 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
268 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
269 AltIntegerData::elt(data, i as usize)
270 }
271
272 const HAS_GET_REGION: bool = true;
273
274 fn get_region(
275 x: crate::ffi::SEXP,
276 start: crate::ffi::R_xlen_t,
277 len: crate::ffi::R_xlen_t,
278 buf: &mut [i32],
279 ) -> crate::ffi::R_xlen_t {
280 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
281 AltIntegerData::get_region(data, start as usize, len as usize, buf) as crate::ffi::R_xlen_t
282 }
283}
284
285pub struct SparseIterRealData<I: Iterator<Item = f64>> {
290 state: SparseIterState<I, f64>,
291}
292
293impl<I: Iterator<Item = f64>> SparseIterRealData<I> {
294 pub fn from_iter(iter: I, len: usize) -> Self {
296 Self {
297 state: SparseIterState::new(iter, len),
298 }
299 }
300}
301
302impl<I: ExactSizeIterator<Item = f64>> SparseIterRealData<I> {
303 pub fn from_exact_iter(iter: I) -> Self {
305 Self {
306 state: SparseIterState::from_exact_size(iter),
307 }
308 }
309}
310
311impl<I: Iterator<Item = f64>> AltrepLen for SparseIterRealData<I> {
312 fn len(&self) -> usize {
313 self.state.len()
314 }
315}
316
317impl<I: Iterator<Item = f64>> AltRealData for SparseIterRealData<I> {
318 fn elt(&self, i: usize) -> f64 {
319 self.state.get_element(i).unwrap_or(f64::NAN)
320 }
321
322 fn as_slice(&self) -> Option<&[f64]> {
323 None
324 }
325
326 fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
327 fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
328 }
329}
330
331impl<I: Iterator<Item = f64> + 'static> crate::externalptr::TypedExternal
332 for SparseIterRealData<I>
333{
334 const TYPE_NAME: &'static str = "SparseIterRealData";
335 const TYPE_NAME_CSTR: &'static [u8] = b"SparseIterRealData\0";
336 const TYPE_ID_CSTR: &'static [u8] = b"miniextendr_api::altrep::SparseIterRealData\0";
337}
338
339impl<I: Iterator<Item = f64> + 'static> InferBase for SparseIterRealData<I> {
340 const BASE: crate::altrep::RBase = crate::altrep::RBase::Real;
341
342 unsafe fn make_class(
343 class_name: *const i8,
344 pkg_name: *const i8,
345 ) -> crate::ffi::altrep::R_altrep_class_t {
346 unsafe {
347 crate::ffi::altrep::R_make_altreal_class(class_name, pkg_name, core::ptr::null_mut())
348 }
349 }
350
351 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
352 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
353 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
354 unsafe { crate::altrep_bridge::install_real::<Self>(cls) };
355 }
356}
357
358impl<I: Iterator<Item = f64> + 'static> crate::altrep_traits::Altrep for SparseIterRealData<I> {
359 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
360 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
361 data.len() as crate::ffi::R_xlen_t
362 }
363}
364
365impl<I: Iterator<Item = f64> + 'static> crate::altrep_traits::AltVec for SparseIterRealData<I> {}
366
367impl<I: Iterator<Item = f64> + 'static> crate::altrep_traits::AltReal for SparseIterRealData<I> {
368 const HAS_ELT: bool = true;
369
370 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> f64 {
371 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
372 AltRealData::elt(data, i as usize)
373 }
374
375 const HAS_GET_REGION: bool = true;
376
377 fn get_region(
378 x: crate::ffi::SEXP,
379 start: crate::ffi::R_xlen_t,
380 len: crate::ffi::R_xlen_t,
381 buf: &mut [f64],
382 ) -> crate::ffi::R_xlen_t {
383 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
384 AltRealData::get_region(data, start as usize, len as usize, buf) as crate::ffi::R_xlen_t
385 }
386}
387
388pub struct SparseIterLogicalData<I: Iterator<Item = bool>> {
390 state: SparseIterState<I, bool>,
391}
392
393impl<I: Iterator<Item = bool>> SparseIterLogicalData<I> {
394 pub fn from_iter(iter: I, len: usize) -> Self {
396 Self {
397 state: SparseIterState::new(iter, len),
398 }
399 }
400}
401
402impl<I: ExactSizeIterator<Item = bool>> SparseIterLogicalData<I> {
403 pub fn from_exact_iter(iter: I) -> Self {
405 Self {
406 state: SparseIterState::from_exact_size(iter),
407 }
408 }
409}
410
411impl<I: Iterator<Item = bool>> AltrepLen for SparseIterLogicalData<I> {
412 fn len(&self) -> usize {
413 self.state.len()
414 }
415}
416
417impl<I: Iterator<Item = bool>> AltLogicalData for SparseIterLogicalData<I> {
418 fn elt(&self, i: usize) -> Logical {
419 self.state
420 .get_element(i)
421 .map(Logical::from_bool)
422 .unwrap_or(Logical::Na)
423 }
424
425 fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
426 fill_region(start, len, self.len(), buf, |idx| self.elt(idx).to_r_int())
427 }
428}
429
430impl<I: Iterator<Item = bool> + 'static> crate::externalptr::TypedExternal
431 for SparseIterLogicalData<I>
432{
433 const TYPE_NAME: &'static str = "SparseIterLogicalData";
434 const TYPE_NAME_CSTR: &'static [u8] = b"SparseIterLogicalData\0";
435 const TYPE_ID_CSTR: &'static [u8] = b"miniextendr_api::altrep::SparseIterLogicalData\0";
436}
437
438impl<I: Iterator<Item = bool> + 'static> InferBase for SparseIterLogicalData<I> {
439 const BASE: crate::altrep::RBase = crate::altrep::RBase::Logical;
440
441 unsafe fn make_class(
442 class_name: *const i8,
443 pkg_name: *const i8,
444 ) -> crate::ffi::altrep::R_altrep_class_t {
445 unsafe {
446 crate::ffi::altrep::R_make_altlogical_class(class_name, pkg_name, core::ptr::null_mut())
447 }
448 }
449
450 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
451 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
452 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
453 unsafe { crate::altrep_bridge::install_lgl::<Self>(cls) };
454 }
455}
456
457impl<I: Iterator<Item = bool> + 'static> crate::altrep_traits::Altrep for SparseIterLogicalData<I> {
458 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
459 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
460 data.len() as crate::ffi::R_xlen_t
461 }
462}
463
464impl<I: Iterator<Item = bool> + 'static> crate::altrep_traits::AltVec for SparseIterLogicalData<I> {}
465
466impl<I: Iterator<Item = bool> + 'static> crate::altrep_traits::AltLogical
467 for SparseIterLogicalData<I>
468{
469 const HAS_ELT: bool = true;
470
471 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> i32 {
472 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
473 AltLogicalData::elt(data, i as usize).to_r_int()
474 }
475
476 const HAS_GET_REGION: bool = true;
477
478 fn get_region(
479 x: crate::ffi::SEXP,
480 start: crate::ffi::R_xlen_t,
481 len: crate::ffi::R_xlen_t,
482 buf: &mut [i32],
483 ) -> crate::ffi::R_xlen_t {
484 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
485 AltLogicalData::get_region(data, start as usize, len as usize, buf) as crate::ffi::R_xlen_t
486 }
487}
488
489pub struct SparseIterRawData<I: Iterator<Item = u8>> {
491 state: SparseIterState<I, u8>,
492}
493
494impl<I: Iterator<Item = u8>> SparseIterRawData<I> {
495 pub fn from_iter(iter: I, len: usize) -> Self {
497 Self {
498 state: SparseIterState::new(iter, len),
499 }
500 }
501}
502
503impl<I: ExactSizeIterator<Item = u8>> SparseIterRawData<I> {
504 pub fn from_exact_iter(iter: I) -> Self {
506 Self {
507 state: SparseIterState::from_exact_size(iter),
508 }
509 }
510}
511
512impl<I: Iterator<Item = u8>> AltrepLen for SparseIterRawData<I> {
513 fn len(&self) -> usize {
514 self.state.len()
515 }
516}
517
518impl<I: Iterator<Item = u8>> AltRawData for SparseIterRawData<I> {
519 fn elt(&self, i: usize) -> u8 {
520 self.state.get_element(i).unwrap_or(0)
521 }
522
523 fn as_slice(&self) -> Option<&[u8]> {
524 None
525 }
526
527 fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
528 fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
529 }
530}
531
532impl<I: Iterator<Item = u8> + 'static> crate::externalptr::TypedExternal for SparseIterRawData<I> {
533 const TYPE_NAME: &'static str = "SparseIterRawData";
534 const TYPE_NAME_CSTR: &'static [u8] = b"SparseIterRawData\0";
535 const TYPE_ID_CSTR: &'static [u8] = b"miniextendr_api::altrep::SparseIterRawData\0";
536}
537
538impl<I: Iterator<Item = u8> + 'static> InferBase for SparseIterRawData<I> {
539 const BASE: crate::altrep::RBase = crate::altrep::RBase::Raw;
540
541 unsafe fn make_class(
542 class_name: *const i8,
543 pkg_name: *const i8,
544 ) -> crate::ffi::altrep::R_altrep_class_t {
545 unsafe {
546 crate::ffi::altrep::R_make_altraw_class(class_name, pkg_name, core::ptr::null_mut())
547 }
548 }
549
550 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
551 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
552 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
553 unsafe { crate::altrep_bridge::install_raw::<Self>(cls) };
554 }
555}
556
557impl<I: Iterator<Item = u8> + 'static> crate::altrep_traits::Altrep for SparseIterRawData<I> {
558 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
559 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
560 data.len() as crate::ffi::R_xlen_t
561 }
562}
563
564impl<I: Iterator<Item = u8> + 'static> crate::altrep_traits::AltVec for SparseIterRawData<I> {}
565
566impl<I: Iterator<Item = u8> + 'static> crate::altrep_traits::AltRaw for SparseIterRawData<I> {
567 const HAS_ELT: bool = true;
568
569 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> u8 {
570 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
571 AltRawData::elt(data, i as usize)
572 }
573
574 const HAS_GET_REGION: bool = true;
575
576 fn get_region(
577 x: crate::ffi::SEXP,
578 start: crate::ffi::R_xlen_t,
579 len: crate::ffi::R_xlen_t,
580 buf: &mut [u8],
581 ) -> crate::ffi::R_xlen_t {
582 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
583 AltRawData::get_region(data, start as usize, len as usize, buf) as crate::ffi::R_xlen_t
584 }
585}
586
587pub struct SparseIterComplexData<I>
589where
590 I: Iterator<Item = crate::ffi::Rcomplex>,
591{
592 state: SparseIterState<I, crate::ffi::Rcomplex>,
593}
594
595impl<I> SparseIterComplexData<I>
596where
597 I: Iterator<Item = crate::ffi::Rcomplex>,
598{
599 pub fn from_iter(iter: I, len: usize) -> Self {
601 Self {
602 state: SparseIterState::new(iter, len),
603 }
604 }
605}
606
607impl<I> SparseIterComplexData<I>
608where
609 I: ExactSizeIterator<Item = crate::ffi::Rcomplex>,
610{
611 pub fn from_exact_iter(iter: I) -> Self {
613 Self {
614 state: SparseIterState::from_exact_size(iter),
615 }
616 }
617}
618
619impl<I> AltrepLen for SparseIterComplexData<I>
620where
621 I: Iterator<Item = crate::ffi::Rcomplex>,
622{
623 fn len(&self) -> usize {
624 self.state.len()
625 }
626}
627
628impl<I> AltComplexData for SparseIterComplexData<I>
629where
630 I: Iterator<Item = crate::ffi::Rcomplex>,
631{
632 fn elt(&self, i: usize) -> crate::ffi::Rcomplex {
633 self.state.get_element(i).unwrap_or(crate::ffi::Rcomplex {
634 r: f64::NAN,
635 i: f64::NAN,
636 })
637 }
638
639 fn as_slice(&self) -> Option<&[crate::ffi::Rcomplex]> {
640 None
641 }
642
643 fn get_region(&self, start: usize, len: usize, buf: &mut [crate::ffi::Rcomplex]) -> usize {
644 fill_region(start, len, self.len(), buf, |idx| self.elt(idx))
645 }
646}
647
648impl<I: Iterator<Item = crate::ffi::Rcomplex> + 'static> crate::externalptr::TypedExternal
649 for SparseIterComplexData<I>
650{
651 const TYPE_NAME: &'static str = "SparseIterComplexData";
652 const TYPE_NAME_CSTR: &'static [u8] = b"SparseIterComplexData\0";
653 const TYPE_ID_CSTR: &'static [u8] = b"miniextendr_api::altrep::SparseIterComplexData\0";
654}
655
656impl<I: Iterator<Item = crate::ffi::Rcomplex> + 'static> InferBase for SparseIterComplexData<I> {
657 const BASE: crate::altrep::RBase = crate::altrep::RBase::Complex;
658
659 unsafe fn make_class(
660 class_name: *const i8,
661 pkg_name: *const i8,
662 ) -> crate::ffi::altrep::R_altrep_class_t {
663 unsafe {
664 crate::ffi::altrep::R_make_altcomplex_class(class_name, pkg_name, core::ptr::null_mut())
665 }
666 }
667
668 unsafe fn install_methods(cls: crate::ffi::altrep::R_altrep_class_t) {
669 unsafe { crate::altrep_bridge::install_base::<Self>(cls) };
670 unsafe { crate::altrep_bridge::install_vec::<Self>(cls) };
671 unsafe { crate::altrep_bridge::install_cplx::<Self>(cls) };
672 }
673}
674
675impl<I: Iterator<Item = crate::ffi::Rcomplex> + 'static> crate::altrep_traits::Altrep
676 for SparseIterComplexData<I>
677{
678 fn length(x: crate::ffi::SEXP) -> crate::ffi::R_xlen_t {
679 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
680 data.len() as crate::ffi::R_xlen_t
681 }
682}
683
684impl<I: Iterator<Item = crate::ffi::Rcomplex> + 'static> crate::altrep_traits::AltVec
685 for SparseIterComplexData<I>
686{
687}
688
689impl<I: Iterator<Item = crate::ffi::Rcomplex> + 'static> crate::altrep_traits::AltComplex
690 for SparseIterComplexData<I>
691{
692 const HAS_ELT: bool = true;
693
694 fn elt(x: crate::ffi::SEXP, i: crate::ffi::R_xlen_t) -> crate::ffi::Rcomplex {
695 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
696 AltComplexData::elt(data, i as usize)
697 }
698
699 const HAS_GET_REGION: bool = true;
700
701 fn get_region(
702 x: crate::ffi::SEXP,
703 start: crate::ffi::R_xlen_t,
704 len: crate::ffi::R_xlen_t,
705 buf: &mut [crate::ffi::Rcomplex],
706 ) -> crate::ffi::R_xlen_t {
707 let data = unsafe { <Self as crate::altrep_data::AltrepExtract>::altrep_extract_ref(x) };
708 AltComplexData::get_region(data, start as usize, len as usize, buf) as crate::ffi::R_xlen_t
709 }
710}
711