miniextendr_api/altrep_data/
builtins.rs1use std::borrow::Cow;
13use std::ops::Range;
14
15use crate::altrep_traits::NA_REAL;
16use crate::{Rcomplex, SEXP};
17
18use super::{
19 AltComplexData, AltIntegerData, AltLogicalData, AltRawData, AltRealData, AltStringData,
20 AltrepDataptr, AltrepLen, AltrepSerialize, Logical, Sortedness,
21};
22
23macro_rules! impl_len_vec {
27 ($elem:ty) => {
28 impl AltrepLen for Vec<$elem> {
29 fn len(&self) -> usize {
30 Vec::len(self)
31 }
32 }
33 };
34}
35
36macro_rules! impl_len_boxed {
38 ($elem:ty) => {
39 impl AltrepLen for Box<[$elem]> {
40 fn len(&self) -> usize {
41 <[$elem]>::len(self)
42 }
43 }
44 };
45}
46
47macro_rules! impl_len_array {
49 ($elem:ty) => {
50 impl<const N: usize> AltrepLen for [$elem; N] {
51 fn len(&self) -> usize {
52 N
53 }
54 }
55 };
56}
57
58macro_rules! impl_len_slice {
60 ($elem:ty) => {
61 impl AltrepLen for &[$elem] {
62 fn len(&self) -> usize {
63 <[$elem]>::len(self)
64 }
65 }
66 };
67}
68
69macro_rules! impl_dataptr_vec {
71 ($elem:ty) => {
72 impl AltrepDataptr<$elem> for Vec<$elem> {
73 fn dataptr(&mut self, _writable: bool) -> Option<*mut $elem> {
74 Some(self.as_mut_ptr())
75 }
76
77 fn dataptr_or_null(&self) -> Option<*const $elem> {
78 Some(self.as_ptr())
79 }
80 }
81 };
82}
83
84macro_rules! impl_dataptr_boxed {
86 ($elem:ty) => {
87 impl AltrepDataptr<$elem> for Box<[$elem]> {
88 fn dataptr(&mut self, _writable: bool) -> Option<*mut $elem> {
89 Some(self.as_mut_ptr())
90 }
91
92 fn dataptr_or_null(&self) -> Option<*const $elem> {
93 Some(self.as_ptr())
94 }
95 }
96 };
97}
98
99macro_rules! impl_serialize {
104 ($ty:ty) => {
105 impl AltrepSerialize for $ty {
106 fn serialized_state(&self) -> SEXP {
107 use crate::into_r::IntoR;
108 self.clone().into_sexp()
109 }
110
111 fn unserialize(state: SEXP) -> Option<Self> {
112 use crate::from_r::TryFromSexp;
113 <$ty>::try_from_sexp(state).ok()
114 }
115 }
116 };
117}
118macro_rules! impl_altinteger_slice {
142 ($ty:ty) => {
143 impl AltIntegerData for $ty {
144 fn elt(&self, i: usize) -> i32 {
145 self[i]
146 }
147
148 fn as_slice(&self) -> Option<&[i32]> {
149 let s: &[i32] = self;
150 Some(s)
151 }
152
153 fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
154 let s: &[i32] = self;
155 let end = (start + len).min(s.len());
156 let actual_len = end.saturating_sub(start);
157 if actual_len > 0 {
158 buf[..actual_len].copy_from_slice(&s[start..end]);
159 }
160 actual_len
161 }
162
163 fn no_na(&self) -> Option<bool> {
164 let s: &[i32] = self;
165 Some(!s.contains(&i32::MIN))
166 }
167
168 fn sum(&self, na_rm: bool) -> Option<i64> {
169 let s: &[i32] = self;
170 let mut sum: i64 = 0;
171 for &x in s.iter() {
172 if x == i32::MIN {
173 if !na_rm {
174 return None; }
176 } else {
177 sum += x as i64;
178 }
179 }
180 Some(sum)
181 }
182
183 fn min(&self, na_rm: bool) -> Option<i32> {
184 let s: &[i32] = self;
185 let mut min = i32::MAX;
186 let mut found = false;
187 for &x in s.iter() {
188 if x == i32::MIN {
189 if !na_rm {
190 return None;
191 }
192 } else {
193 found = true;
194 min = min.min(x);
195 }
196 }
197 if found { Some(min) } else { None }
198 }
199
200 fn max(&self, na_rm: bool) -> Option<i32> {
201 let s: &[i32] = self;
202 let mut max = i32::MIN + 1; let mut found = false;
204 for &x in s.iter() {
205 if x == i32::MIN {
206 if !na_rm {
207 return None;
208 }
209 } else {
210 found = true;
211 max = max.max(x);
212 }
213 }
214 if found { Some(max) } else { None }
215 }
216 }
217 };
218}
219
220macro_rules! impl_altreal_slice {
225 ($ty:ty) => {
226 impl AltRealData for $ty {
227 fn elt(&self, i: usize) -> f64 {
228 self[i]
229 }
230
231 fn as_slice(&self) -> Option<&[f64]> {
232 let s: &[f64] = self;
233 Some(s)
234 }
235
236 fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
237 let s: &[f64] = self;
238 let end = (start + len).min(s.len());
239 let actual_len = end.saturating_sub(start);
240 if actual_len > 0 {
241 buf[..actual_len].copy_from_slice(&s[start..end]);
242 }
243 actual_len
244 }
245
246 fn no_na(&self) -> Option<bool> {
247 let s: &[f64] = self;
248 Some(!s.iter().any(|x| x.to_bits() == NA_REAL.to_bits()))
249 }
250
251 fn sum(&self, na_rm: bool) -> Option<f64> {
252 let s: &[f64] = self;
253 let mut sum = 0.0;
254 for &x in s.iter() {
255 if x.to_bits() == NA_REAL.to_bits() {
256 if !na_rm {
257 return Some(NA_REAL);
258 }
259 } else if x.is_nan() {
260 if !na_rm {
261 return Some(f64::NAN);
262 }
263 } else {
264 sum += x;
265 }
266 }
267 Some(sum)
268 }
269
270 fn min(&self, na_rm: bool) -> Option<f64> {
271 let s: &[f64] = self;
272 let mut min = f64::INFINITY;
273 let mut found = false;
274 for &x in s.iter() {
275 if x.to_bits() == NA_REAL.to_bits() {
276 if !na_rm {
277 return Some(NA_REAL);
278 }
279 } else if x.is_nan() {
280 if !na_rm {
281 return Some(f64::NAN);
282 }
283 } else {
284 found = true;
285 min = min.min(x);
286 }
287 }
288 if found { Some(min) } else { None }
289 }
290
291 fn max(&self, na_rm: bool) -> Option<f64> {
292 let s: &[f64] = self;
293 let mut max = f64::NEG_INFINITY;
294 let mut found = false;
295 for &x in s.iter() {
296 if x.to_bits() == NA_REAL.to_bits() {
297 if !na_rm {
298 return Some(NA_REAL);
299 }
300 } else if x.is_nan() {
301 if !na_rm {
302 return Some(f64::NAN);
303 }
304 } else {
305 found = true;
306 max = max.max(x);
307 }
308 }
309 if found { Some(max) } else { None }
310 }
311 }
312 };
313}
314
315macro_rules! impl_altraw_slice {
317 ($ty:ty) => {
318 impl AltRawData for $ty {
319 fn elt(&self, i: usize) -> u8 {
320 self[i]
321 }
322
323 fn as_slice(&self) -> Option<&[u8]> {
324 let s: &[u8] = self;
325 Some(s)
326 }
327
328 fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
329 let s: &[u8] = self;
330 let end = (start + len).min(s.len());
331 let actual_len = end.saturating_sub(start);
332 if actual_len > 0 {
333 buf[..actual_len].copy_from_slice(&s[start..end]);
334 }
335 actual_len
336 }
337 }
338 };
339}
340
341macro_rules! impl_altcomplex_slice {
343 ($ty:ty) => {
344 impl AltComplexData for $ty {
345 fn elt(&self, i: usize) -> Rcomplex {
346 self[i]
347 }
348
349 fn as_slice(&self) -> Option<&[Rcomplex]> {
350 let s: &[Rcomplex] = self;
351 Some(s)
352 }
353
354 fn get_region(&self, start: usize, len: usize, buf: &mut [Rcomplex]) -> usize {
355 let s: &[Rcomplex] = self;
356 let end = (start + len).min(s.len());
357 let actual_len = end.saturating_sub(start);
358 if actual_len > 0 {
359 buf[..actual_len].copy_from_slice(&s[start..end]);
360 }
361 actual_len
362 }
363 }
364 };
365}
366
367macro_rules! impl_altlogical_slice {
369 ($ty:ty) => {
370 impl AltLogicalData for $ty {
371 fn elt(&self, i: usize) -> Logical {
372 self[i].into()
373 }
374
375 fn no_na(&self) -> Option<bool> {
376 Some(true) }
378
379 fn sum(&self, _na_rm: bool) -> Option<i64> {
380 let s: &[bool] = self;
381 Some(s.iter().filter(|&&x| x).count() as i64)
382 }
383 }
384 };
385}
386impl_serialize!(Vec<i32>);
391impl_serialize!(Vec<f64>);
392impl_serialize!(Vec<u8>);
393impl_serialize!(Vec<bool>);
394impl_serialize!(Vec<String>);
395impl_serialize!(Vec<Option<String>>);
396impl_serialize!(Vec<Rcomplex>);
397impl_serialize!(Vec<std::borrow::Cow<'static, str>>);
400impl_serialize!(Vec<Option<std::borrow::Cow<'static, str>>>);
401impl AltrepSerialize for Box<[i32]> {
409 fn serialized_state(&self) -> SEXP {
410 use crate::into_r::IntoR;
411 self.to_vec().into_sexp()
412 }
413
414 fn unserialize(state: SEXP) -> Option<Self> {
415 use crate::from_r::TryFromSexp;
416 Vec::<i32>::try_from_sexp(state)
417 .ok()
418 .map(|v| v.into_boxed_slice())
419 }
420}
421
422impl AltrepSerialize for Box<[f64]> {
423 fn serialized_state(&self) -> SEXP {
424 use crate::into_r::IntoR;
425 self.to_vec().into_sexp()
426 }
427
428 fn unserialize(state: SEXP) -> Option<Self> {
429 use crate::from_r::TryFromSexp;
430 Vec::<f64>::try_from_sexp(state)
431 .ok()
432 .map(|v| v.into_boxed_slice())
433 }
434}
435
436impl AltrepSerialize for Box<[u8]> {
437 fn serialized_state(&self) -> SEXP {
438 use crate::into_r::IntoR;
439 self.to_vec().into_sexp()
440 }
441
442 fn unserialize(state: SEXP) -> Option<Self> {
443 use crate::from_r::TryFromSexp;
444 Vec::<u8>::try_from_sexp(state)
445 .ok()
446 .map(|v| v.into_boxed_slice())
447 }
448}
449
450impl AltrepSerialize for Box<[bool]> {
451 fn serialized_state(&self) -> SEXP {
452 use crate::into_r::IntoR;
453 self.to_vec().into_sexp()
454 }
455
456 fn unserialize(state: SEXP) -> Option<Self> {
457 use crate::from_r::TryFromSexp;
458 Vec::<bool>::try_from_sexp(state)
459 .ok()
460 .map(|v| v.into_boxed_slice())
461 }
462}
463
464impl AltrepSerialize for Box<[String]> {
465 fn serialized_state(&self) -> SEXP {
466 use crate::into_r::IntoR;
467 self.to_vec().into_sexp()
468 }
469
470 fn unserialize(state: SEXP) -> Option<Self> {
471 use crate::from_r::TryFromSexp;
472 Vec::<String>::try_from_sexp(state)
473 .ok()
474 .map(|v| v.into_boxed_slice())
475 }
476}
477
478impl AltrepSerialize for Box<[Rcomplex]> {
479 fn serialized_state(&self) -> SEXP {
480 use crate::into_r::IntoR;
481 self.to_vec().into_sexp()
482 }
483
484 fn unserialize(state: SEXP) -> Option<Self> {
485 use crate::from_r::TryFromSexp;
486 Vec::<Rcomplex>::try_from_sexp(state)
487 .ok()
488 .map(|v| v.into_boxed_slice())
489 }
490}
491impl_len_vec!(i32);
496impl_altinteger_slice!(Vec<i32>);
497impl_dataptr_vec!(i32);
498
499impl_len_vec!(f64);
500impl_altreal_slice!(Vec<f64>);
501impl_dataptr_vec!(f64);
502
503impl_len_vec!(u8);
504impl_altraw_slice!(Vec<u8>);
505impl_dataptr_vec!(u8);
506
507impl_len_vec!(String);
508
509impl AltStringData for Vec<String> {
510 fn elt(&self, i: usize) -> Option<&str> {
511 Some(self[i].as_str())
512 }
513
514 fn no_na(&self) -> Option<bool> {
515 Some(true) }
517}
518
519impl_len_vec!(Option<String>);
520
521impl AltStringData for Vec<Option<String>> {
522 fn elt(&self, i: usize) -> Option<&str> {
523 self[i].as_deref()
524 }
525
526 fn no_na(&self) -> Option<bool> {
527 Some(!self.iter().any(|x| x.is_none()))
528 }
529}
530
531impl AltrepLen for Vec<std::borrow::Cow<'static, str>> {
532 fn len(&self) -> usize {
533 self.len()
534 }
535}
536
537impl AltStringData for Vec<std::borrow::Cow<'static, str>> {
538 fn elt(&self, i: usize) -> Option<&str> {
539 Some(self[i].as_ref())
540 }
541
542 fn no_na(&self) -> Option<bool> {
543 Some(true) }
545}
546
547impl AltrepLen for Vec<Option<std::borrow::Cow<'static, str>>> {
548 fn len(&self) -> usize {
549 self.len()
550 }
551}
552
553impl AltStringData for Vec<Option<std::borrow::Cow<'static, str>>> {
554 fn elt(&self, i: usize) -> Option<&str> {
555 self[i].as_deref()
556 }
557
558 fn no_na(&self) -> Option<bool> {
559 Some(!self.iter().any(|x| x.is_none()))
560 }
561}
562
563impl_len_vec!(bool);
564impl_altlogical_slice!(Vec<bool>);
565impl_len_boxed!(i32);
581impl_altinteger_slice!(Box<[i32]>);
582impl_dataptr_boxed!(i32);
583
584impl_len_boxed!(f64);
585impl_altreal_slice!(Box<[f64]>);
586impl_dataptr_boxed!(f64);
587
588impl_len_boxed!(u8);
589impl_altraw_slice!(Box<[u8]>);
590impl_dataptr_boxed!(u8);
591
592impl_len_boxed!(bool);
593impl_altlogical_slice!(Box<[bool]>);
594
595impl_len_boxed!(String);
596
597impl AltStringData for Box<[String]> {
598 fn elt(&self, i: usize) -> Option<&str> {
599 Some(self[i].as_str())
600 }
601
602 fn no_na(&self) -> Option<bool> {
603 Some(true) }
605}
606impl AltrepSerialize for Range<i32> {
612 fn serialized_state(&self) -> SEXP {
613 use crate::into_r::IntoR;
614 vec![self.start, self.end].into_sexp()
615 }
616
617 fn unserialize(state: SEXP) -> Option<Self> {
618 use crate::from_r::TryFromSexp;
619 let v = Vec::<i32>::try_from_sexp(state).ok()?;
620 if v.len() == 2 { Some(v[0]..v[1]) } else { None }
621 }
622}
623
624impl AltrepSerialize for Range<i64> {
625 fn serialized_state(&self) -> SEXP {
626 use crate::into_r::IntoR;
627 vec![
630 f64::from_bits(self.start as u64),
631 f64::from_bits(self.end as u64),
632 ]
633 .into_sexp()
634 }
635
636 fn unserialize(state: SEXP) -> Option<Self> {
637 use crate::from_r::TryFromSexp;
638 let v = Vec::<f64>::try_from_sexp(state).ok()?;
639 if v.len() == 2 {
640 Some((v[0].to_bits() as i64)..(v[1].to_bits() as i64))
641 } else {
642 None
643 }
644 }
645}
646
647impl AltrepSerialize for Range<f64> {
648 fn serialized_state(&self) -> SEXP {
649 use crate::into_r::IntoR;
650 vec![self.start, self.end].into_sexp()
651 }
652
653 fn unserialize(state: SEXP) -> Option<Self> {
654 use crate::from_r::TryFromSexp;
655 let v = Vec::<f64>::try_from_sexp(state).ok()?;
656 if v.len() == 2 { Some(v[0]..v[1]) } else { None }
657 }
658}
659impl AltrepLen for Range<i32> {
664 fn len(&self) -> usize {
665 if self.end > self.start {
666 (self.end - self.start) as usize
667 } else {
668 0
669 }
670 }
671}
672
673impl AltIntegerData for Range<i32> {
674 fn elt(&self, i: usize) -> i32 {
675 self.start + i as i32
676 }
677
678 fn is_sorted(&self) -> Option<Sortedness> {
679 Some(Sortedness::Increasing)
680 }
681
682 fn no_na(&self) -> Option<bool> {
683 let contains_na = self.start == i32::MIN && self.end > i32::MIN;
687 Some(!contains_na)
688 }
689
690 fn sum(&self, na_rm: bool) -> Option<i64> {
691 let n = AltrepLen::len(self) as i64;
692 if n == 0 {
693 return Some(0);
694 }
695
696 let contains_na = self.start == i32::MIN && self.end > i32::MIN;
698 if contains_na && !na_rm {
699 return None; }
701
702 if contains_na {
705 let n_valid = n - 1;
707 if n_valid == 0 {
708 return Some(0);
709 }
710 let first = (self.start + 1) as i64;
711 let last = (self.end - 1) as i64;
712 Some(n_valid * (first + last) / 2)
713 } else {
714 let first = self.start as i64;
715 let last = (self.end - 1) as i64;
716 Some(n * (first + last) / 2)
717 }
718 }
719
720 fn min(&self, na_rm: bool) -> Option<i32> {
721 if AltrepLen::len(self) == 0 {
722 return None;
723 }
724
725 if self.start == i32::MIN {
727 if na_rm {
728 if self.end > self.start + 1 {
730 Some(self.start + 1)
731 } else {
732 None }
734 } else {
735 None }
737 } else {
738 Some(self.start)
739 }
740 }
741
742 fn max(&self, na_rm: bool) -> Option<i32> {
743 if AltrepLen::len(self) == 0 {
744 return None;
745 }
746
747 let contains_na = self.start == i32::MIN && self.end > i32::MIN;
750 if contains_na && !na_rm {
751 return None; }
753
754 Some(self.end - 1)
757 }
758}
759
760impl AltrepLen for Range<i64> {
761 fn len(&self) -> usize {
762 if self.end > self.start {
763 (self.end - self.start) as usize
764 } else {
765 0
766 }
767 }
768}
769
770impl AltIntegerData for Range<i64> {
771 fn elt(&self, i: usize) -> i32 {
772 let val = self.start.saturating_add(i as i64);
773 if val > i32::MAX as i64 || val <= i32::MIN as i64 {
776 crate::altrep_traits::NA_INTEGER
777 } else {
778 val as i32
779 }
780 }
781
782 fn is_sorted(&self) -> Option<Sortedness> {
783 Some(Sortedness::Increasing)
784 }
785
786 fn no_na(&self) -> Option<bool> {
787 let na_sentinel = i32::MIN as i64;
797 let i32_max = i32::MAX as i64;
798
799 let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
801
802 let has_underflow = self.start < na_sentinel;
805 let has_overflow = (self.end - 1) > i32_max;
806
807 Some(!contains_na_sentinel && !has_underflow && !has_overflow)
808 }
809
810 fn sum(&self, na_rm: bool) -> Option<i64> {
811 let n = AltrepLen::len(self) as i64;
812 if n == 0 {
813 return Some(0);
814 }
815
816 let na_sentinel = i32::MIN as i64;
818 let i32_max = i32::MAX as i64;
819 let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
820 let has_underflow = self.start < na_sentinel;
821 let has_overflow = (self.end - 1) > i32_max;
822 let has_na = contains_na_sentinel || has_underflow || has_overflow;
823
824 if has_na && !na_rm {
825 return None; }
827
828 if has_na {
829 return None;
832 }
833
834 let first = self.start;
835 let last = self.end - 1;
836
837 let sum_endpoints = first.checked_add(last)?;
840 let product = n.checked_mul(sum_endpoints)?;
841 Some(product / 2)
842 }
843
844 fn min(&self, na_rm: bool) -> Option<i32> {
845 if AltrepLen::len(self) == 0 {
846 return None;
847 }
848
849 let na_sentinel = i32::MIN as i64;
850 let i32_max = i32::MAX as i64;
851
852 let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
854 let has_underflow = self.start < na_sentinel;
855 let has_overflow = (self.end - 1) > i32_max;
856 let has_na = contains_na_sentinel || has_underflow || has_overflow;
857
858 if has_na && !na_rm {
859 return None; }
861
862 if has_na {
863 return None;
866 }
867
868 Some(self.start as i32)
870 }
871
872 fn max(&self, na_rm: bool) -> Option<i32> {
873 if AltrepLen::len(self) == 0 {
874 return None;
875 }
876
877 let na_sentinel = i32::MIN as i64;
878 let i32_max = i32::MAX as i64;
879
880 let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
882 let has_underflow = self.start < na_sentinel;
883 let has_overflow = (self.end - 1) > i32_max;
884 let has_na = contains_na_sentinel || has_underflow || has_overflow;
885
886 if has_na && !na_rm {
887 return None; }
889
890 if has_na {
891 return None;
894 }
895
896 Some((self.end - 1) as i32)
898 }
899}
900
901impl AltrepLen for Range<f64> {
902 fn len(&self) -> usize {
903 if self.end > self.start {
905 (self.end - self.start).ceil() as usize
906 } else {
907 0
908 }
909 }
910}
911
912impl AltRealData for Range<f64> {
913 fn elt(&self, i: usize) -> f64 {
914 self.start + i as f64
915 }
916
917 fn is_sorted(&self) -> Option<Sortedness> {
918 Some(Sortedness::Increasing)
919 }
920
921 fn no_na(&self) -> Option<bool> {
922 Some(true)
923 }
924
925 fn sum(&self, _na_rm: bool) -> Option<f64> {
926 let n = AltrepLen::len(self) as f64;
927 if n == 0.0 {
928 return Some(0.0);
929 }
930 let first = self.start;
931 let last = self.start + (n - 1.0);
932 Some(n * (first + last) / 2.0)
933 }
934
935 fn min(&self, _na_rm: bool) -> Option<f64> {
936 if AltrepLen::len(self) > 0 {
937 Some(self.start)
938 } else {
939 None
940 }
941 }
942
943 fn max(&self, _na_rm: bool) -> Option<f64> {
944 if AltrepLen::len(self) > 0 {
945 Some(self.start + (AltrepLen::len(self) - 1) as f64)
946 } else {
947 None
948 }
949 }
950}
951impl_len_slice!(i32);
956impl_altinteger_slice!(&[i32]);
957
958impl_len_slice!(f64);
959impl_altreal_slice!(&[f64]);
960
961impl_len_slice!(u8);
962impl_altraw_slice!(&[u8]);
963
964impl_len_slice!(bool);
965impl_altlogical_slice!(&[bool]);
966
967impl_len_slice!(String);
968
969impl AltStringData for &[String] {
970 fn elt(&self, i: usize) -> Option<&str> {
971 Some(self[i].as_str())
972 }
973}
974
975impl_len_slice!(&str);
976
977impl AltStringData for &[&str] {
978 fn elt(&self, i: usize) -> Option<&str> {
979 Some(self[i])
980 }
981}
982impl_len_array!(i32);
1002
1003impl<const N: usize> AltIntegerData for [i32; N] {
1004 fn elt(&self, i: usize) -> i32 {
1005 self[i]
1006 }
1007
1008 fn as_slice(&self) -> Option<&[i32]> {
1009 Some(self.as_slice())
1010 }
1011
1012 fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
1013 let end = (start + len).min(N);
1014 let actual_len = end.saturating_sub(start);
1015 if actual_len > 0 {
1016 buf[..actual_len].copy_from_slice(&self[start..end]);
1017 }
1018 actual_len
1019 }
1020
1021 fn no_na(&self) -> Option<bool> {
1022 Some(!self.contains(&i32::MIN))
1023 }
1024}
1025
1026impl_len_array!(f64);
1027
1028impl<const N: usize> AltRealData for [f64; N] {
1029 fn elt(&self, i: usize) -> f64 {
1030 self[i]
1031 }
1032
1033 fn as_slice(&self) -> Option<&[f64]> {
1034 Some(self.as_slice())
1035 }
1036
1037 fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
1038 let end = (start + len).min(N);
1039 let actual_len = end.saturating_sub(start);
1040 if actual_len > 0 {
1041 buf[..actual_len].copy_from_slice(&self[start..end]);
1042 }
1043 actual_len
1044 }
1045
1046 fn no_na(&self) -> Option<bool> {
1047 Some(!self.iter().any(|x| x.to_bits() == NA_REAL.to_bits()))
1048 }
1049}
1050
1051impl_len_array!(bool);
1052
1053impl<const N: usize> AltLogicalData for [bool; N] {
1054 fn elt(&self, i: usize) -> Logical {
1055 Logical::from_bool(self[i])
1056 }
1057
1058 fn no_na(&self) -> Option<bool> {
1059 Some(true) }
1061}
1062
1063impl_len_array!(u8);
1064
1065impl<const N: usize> AltRawData for [u8; N] {
1066 fn elt(&self, i: usize) -> u8 {
1067 self[i]
1068 }
1069
1070 fn as_slice(&self) -> Option<&[u8]> {
1071 Some(self.as_slice())
1072 }
1073
1074 fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
1075 let end = (start + len).min(N);
1076 let actual_len = end.saturating_sub(start);
1077 if actual_len > 0 {
1078 buf[..actual_len].copy_from_slice(&self[start..end]);
1079 }
1080 actual_len
1081 }
1082}
1083
1084impl_len_array!(String);
1085
1086impl<const N: usize> AltStringData for [String; N] {
1087 fn elt(&self, i: usize) -> Option<&str> {
1088 Some(self[i].as_str())
1089 }
1090}
1091impl_len_vec!(Rcomplex);
1096impl_altcomplex_slice!(Vec<Rcomplex>);
1097impl_dataptr_vec!(Rcomplex);
1098impl_len_boxed!(Rcomplex);
1103impl_altcomplex_slice!(Box<[Rcomplex]>);
1104impl_dataptr_boxed!(Rcomplex);
1105impl_len_array!(Rcomplex);
1110
1111impl<const N: usize> AltComplexData for [Rcomplex; N] {
1112 fn elt(&self, i: usize) -> Rcomplex {
1113 self[i]
1114 }
1115
1116 fn as_slice(&self) -> Option<&[Rcomplex]> {
1117 Some(self.as_slice())
1118 }
1119
1120 fn get_region(&self, start: usize, len: usize, buf: &mut [Rcomplex]) -> usize {
1121 let end = (start + len).min(N);
1122 let actual_len = end.saturating_sub(start);
1123 if actual_len > 0 {
1124 buf[..actual_len].copy_from_slice(&self[start..end]);
1125 }
1126 actual_len
1127 }
1128}
1129macro_rules! impl_len_cow {
1139 ($elem:ty) => {
1140 impl AltrepLen for Cow<'static, [$elem]> {
1141 fn len(&self) -> usize {
1142 <[$elem]>::len(self)
1143 }
1144 }
1145 };
1146}
1147
1148macro_rules! impl_dataptr_cow {
1149 ($elem:ty) => {
1150 impl AltrepDataptr<$elem> for Cow<'static, [$elem]> {
1151 fn dataptr(&mut self, writable: bool) -> Option<*mut $elem> {
1152 if writable {
1153 Some(self.to_mut().as_mut_ptr())
1156 } else {
1157 Some(self.as_ptr().cast_mut())
1160 }
1161 }
1162
1163 fn dataptr_or_null(&self) -> Option<*const $elem> {
1164 Some(self.as_ptr())
1165 }
1166 }
1167 };
1168}
1169
1170macro_rules! impl_serialize_cow {
1171 ($elem:ty) => {
1172 impl AltrepSerialize for Cow<'static, [$elem]> {
1173 fn serialized_state(&self) -> SEXP {
1174 use crate::into_r::IntoR;
1175 self.clone().into_sexp()
1176 }
1177
1178 fn unserialize(state: SEXP) -> Option<Self> {
1179 use crate::from_r::TryFromSexp;
1180 Cow::<'static, [$elem]>::try_from_sexp(state).ok()
1181 }
1182 }
1183 };
1184}
1185
1186impl_len_cow!(i32);
1187impl_altinteger_slice!(Cow<'static, [i32]>);
1188impl_dataptr_cow!(i32);
1189impl_serialize_cow!(i32);
1190
1191impl_len_cow!(f64);
1192impl_altreal_slice!(Cow<'static, [f64]>);
1193impl_dataptr_cow!(f64);
1194impl_serialize_cow!(f64);
1195
1196impl_len_cow!(u8);
1197impl_altraw_slice!(Cow<'static, [u8]>);
1198impl_dataptr_cow!(u8);
1199impl_serialize_cow!(u8);
1200
1201impl_len_cow!(Rcomplex);
1202impl_altcomplex_slice!(Cow<'static, [Rcomplex]>);
1203impl_dataptr_cow!(Rcomplex);
1204impl_serialize_cow!(Rcomplex);
1205#[cfg(test)]
1221mod tests {
1222 use super::*;
1223 use crate::altrep_data::AltRealData;
1224
1225 #[test]
1229 fn na_real_bit_pattern() {
1230 assert_eq!(NA_REAL.to_bits(), 0x7FF0_0000_0000_07A2);
1231 }
1232
1233 #[test]
1235 fn nan_is_not_na_real() {
1236 let nan = f64::NAN;
1237 assert!(nan.is_nan());
1238 assert_ne!(nan.to_bits(), NA_REAL.to_bits());
1239 }
1240
1241 #[test]
1248 fn vec_f64_no_na_with_regular_nan_is_true() {
1249 let v: Vec<f64> = vec![1.0, f64::NAN, 3.0];
1250 assert_eq!(AltRealData::no_na(&v), Some(true));
1251 }
1252
1253 #[test]
1255 fn vec_f64_no_na_with_na_real_is_false() {
1256 let v: Vec<f64> = vec![1.0, NA_REAL, 3.0];
1257 assert_eq!(AltRealData::no_na(&v), Some(false));
1258 }
1259
1260 #[test]
1262 fn vec_f64_no_na_all_finite_is_true() {
1263 let v: Vec<f64> = vec![1.0, 2.0, 3.0];
1264 assert_eq!(AltRealData::no_na(&v), Some(true));
1265 }
1266
1267 #[test]
1273 fn vec_f64_sum_na_propagates() {
1274 let v: Vec<f64> = vec![1.0, NA_REAL, 3.0];
1275 let result = AltRealData::sum(&v, false);
1276 assert!(result.is_some());
1277 let bits = result.unwrap().to_bits();
1278 assert_eq!(
1279 bits,
1280 NA_REAL.to_bits(),
1281 "sum with NA should return NA_real_"
1282 );
1283 }
1284
1285 #[test]
1287 fn vec_f64_sum_na_rm_skips_na() {
1288 let v: Vec<f64> = vec![1.0, NA_REAL, 3.0];
1289 let result = AltRealData::sum(&v, true);
1290 assert_eq!(result, Some(4.0));
1291 }
1292
1293 #[test]
1295 fn vec_f64_sum_nan_propagates_as_nan_not_na() {
1296 let v: Vec<f64> = vec![1.0, f64::NAN, 3.0];
1297 let result = AltRealData::sum(&v, false);
1298 assert!(result.is_some());
1299 let val = result.unwrap();
1300 assert!(val.is_nan(), "sum with NaN (not NA) should return NaN");
1301 assert_ne!(
1302 val.to_bits(),
1303 NA_REAL.to_bits(),
1304 "sum with regular NaN should NOT return NA_real_"
1305 );
1306 }
1307
1308 #[test]
1310 fn vec_f64_sum_nan_rm_skips_nan() {
1311 let v: Vec<f64> = vec![1.0, f64::NAN, 3.0];
1312 let result = AltRealData::sum(&v, true);
1313 assert_eq!(result, Some(4.0));
1314 }
1315
1316 #[test]
1321 fn box_f64_no_na_with_regular_nan_is_true() {
1322 let v: Box<[f64]> = vec![1.0, f64::NAN, 3.0].into_boxed_slice();
1323 assert_eq!(AltRealData::no_na(&v), Some(true));
1324 }
1325
1326 #[test]
1327 fn box_f64_no_na_with_na_real_is_false() {
1328 let v: Box<[f64]> = vec![1.0, NA_REAL, 3.0].into_boxed_slice();
1329 assert_eq!(AltRealData::no_na(&v), Some(false));
1330 }
1331
1332 #[test]
1337 fn slice_f64_no_na_with_regular_nan_is_true() {
1338 let data: &[f64] = &[1.0, f64::NAN, 3.0];
1339 assert_eq!(AltRealData::no_na(&data), Some(true));
1340 }
1341
1342 #[test]
1343 fn slice_f64_no_na_with_na_real_is_false() {
1344 let data: &[f64] = &[1.0, NA_REAL, 3.0];
1345 assert_eq!(AltRealData::no_na(&data), Some(false));
1346 }
1347
1348 #[test]
1353 fn array_f64_no_na_with_regular_nan_is_true() {
1354 let arr: [f64; 3] = [1.0, f64::NAN, 3.0];
1355 assert_eq!(AltRealData::no_na(&arr), Some(true));
1356 }
1357
1358 #[test]
1359 fn array_f64_no_na_with_na_real_is_false() {
1360 let arr: [f64; 3] = [1.0, NA_REAL, 3.0];
1361 assert_eq!(AltRealData::no_na(&arr), Some(false));
1362 }
1363
1364 #[test]
1369 fn cow_f64_no_na_with_regular_nan_is_true() {
1370 let v: Cow<'static, [f64]> = Cow::Owned(vec![1.0, f64::NAN, 3.0]);
1371 assert_eq!(AltRealData::no_na(&v), Some(true));
1372 }
1373
1374 #[test]
1375 fn cow_f64_no_na_with_na_real_is_false() {
1376 let v: Cow<'static, [f64]> = Cow::Owned(vec![1.0, NA_REAL, 3.0]);
1377 assert_eq!(AltRealData::no_na(&v), Some(false));
1378 }
1379
1380 }