Skip to main content

miniextendr_api/altrep_data/
builtins.rs

1//! Built-in ALTREP data implementations for standard Rust types.
2//!
3//! Provides `AltIntegerData`, `AltRealData`, `AltLogicalData`, `AltRawData`,
4//! `AltStringData`, and `AltComplexData` implementations for:
5//!
6//! - `Vec<T>` — owned vector (most common)
7//! - `Box<[T]>` — boxed slice
8//! - `Range<T>` — lazy arithmetic sequences (integer, real)
9//! - `&'static [T]` — borrowed slices (zero-copy from static data)
10//! - `[T; N]` — fixed-size arrays
11
12use std::ops::Range;
13
14use crate::ffi::Rcomplex;
15use crate::ffi::SEXP;
16
17use super::{
18    AltComplexData, AltIntegerData, AltLogicalData, AltRawData, AltRealData, AltStringData,
19    AltrepDataptr, AltrepLen, AltrepSerialize, Logical, Sortedness,
20};
21
22// region: Helper macros to reduce repetition
23
24/// Implement AltrepLen for Vec<$elem>
25macro_rules! impl_len_vec {
26    ($elem:ty) => {
27        impl AltrepLen for Vec<$elem> {
28            fn len(&self) -> usize {
29                Vec::len(self)
30            }
31        }
32    };
33}
34
35/// Implement AltrepLen for Box<[$elem]>
36macro_rules! impl_len_boxed {
37    ($elem:ty) => {
38        impl AltrepLen for Box<[$elem]> {
39            fn len(&self) -> usize {
40                <[$elem]>::len(self)
41            }
42        }
43    };
44}
45
46/// Implement AltrepLen for [$elem; N]
47macro_rules! impl_len_array {
48    ($elem:ty) => {
49        impl<const N: usize> AltrepLen for [$elem; N] {
50            fn len(&self) -> usize {
51                N
52            }
53        }
54    };
55}
56
57/// Implement AltrepLen for &[$elem]
58macro_rules! impl_len_slice {
59    ($elem:ty) => {
60        impl AltrepLen for &[$elem] {
61            fn len(&self) -> usize {
62                <[$elem]>::len(self)
63            }
64        }
65    };
66}
67
68/// Implement AltrepDataptr for Vec<$elem> (types with direct memory access)
69macro_rules! impl_dataptr_vec {
70    ($elem:ty) => {
71        impl AltrepDataptr<$elem> for Vec<$elem> {
72            fn dataptr(&mut self, _writable: bool) -> Option<*mut $elem> {
73                Some(self.as_mut_ptr())
74            }
75
76            fn dataptr_or_null(&self) -> Option<*const $elem> {
77                Some(self.as_ptr())
78            }
79        }
80    };
81}
82
83/// Implement AltrepDataptr for Box<[$elem]> (types with direct memory access)
84macro_rules! impl_dataptr_boxed {
85    ($elem:ty) => {
86        impl AltrepDataptr<$elem> for Box<[$elem]> {
87            fn dataptr(&mut self, _writable: bool) -> Option<*mut $elem> {
88                Some(self.as_mut_ptr())
89            }
90
91            fn dataptr_or_null(&self) -> Option<*const $elem> {
92                Some(self.as_ptr())
93            }
94        }
95    };
96}
97
98/// Implement AltrepSerialize for types that can be cloned and converted to/from R.
99///
100/// This serializes by converting to a native R vector, ensuring the data survives
101/// even if the Rust package isn't loaded when unserializing.
102macro_rules! impl_serialize {
103    ($ty:ty) => {
104        impl AltrepSerialize for $ty {
105            fn serialized_state(&self) -> SEXP {
106                use crate::into_r::IntoR;
107                self.clone().into_sexp()
108            }
109
110            fn unserialize(state: SEXP) -> Option<Self> {
111                use crate::from_r::TryFromSexp;
112                <$ty>::try_from_sexp(state).ok()
113            }
114        }
115    };
116}
117// endregion
118
119// region: AltrepSerialize implementations for Vec<T>
120
121impl_serialize!(Vec<i32>);
122impl_serialize!(Vec<f64>);
123impl_serialize!(Vec<u8>);
124impl_serialize!(Vec<bool>);
125impl_serialize!(Vec<String>);
126impl_serialize!(Vec<Option<String>>);
127impl_serialize!(Vec<Rcomplex>);
128// Cow string vectors: serialize hits R's CHARSXP cache (no string data copy),
129// unserialize borrows via charsxp_to_cow (zero-copy for UTF-8).
130impl_serialize!(Vec<std::borrow::Cow<'static, str>>);
131impl_serialize!(Vec<Option<std::borrow::Cow<'static, str>>>);
132// endregion
133
134// region: AltrepSerialize implementations for Box<[T]>
135
136// Box<[T]> types don't have direct TryFromSexp implementations, so we manually
137// implement serialization by converting to Vec and back.
138
139impl AltrepSerialize for Box<[i32]> {
140    fn serialized_state(&self) -> SEXP {
141        use crate::into_r::IntoR;
142        self.to_vec().into_sexp()
143    }
144
145    fn unserialize(state: SEXP) -> Option<Self> {
146        use crate::from_r::TryFromSexp;
147        Vec::<i32>::try_from_sexp(state)
148            .ok()
149            .map(|v| v.into_boxed_slice())
150    }
151}
152
153impl AltrepSerialize for Box<[f64]> {
154    fn serialized_state(&self) -> SEXP {
155        use crate::into_r::IntoR;
156        self.to_vec().into_sexp()
157    }
158
159    fn unserialize(state: SEXP) -> Option<Self> {
160        use crate::from_r::TryFromSexp;
161        Vec::<f64>::try_from_sexp(state)
162            .ok()
163            .map(|v| v.into_boxed_slice())
164    }
165}
166
167impl AltrepSerialize for Box<[u8]> {
168    fn serialized_state(&self) -> SEXP {
169        use crate::into_r::IntoR;
170        self.to_vec().into_sexp()
171    }
172
173    fn unserialize(state: SEXP) -> Option<Self> {
174        use crate::from_r::TryFromSexp;
175        Vec::<u8>::try_from_sexp(state)
176            .ok()
177            .map(|v| v.into_boxed_slice())
178    }
179}
180
181impl AltrepSerialize for Box<[bool]> {
182    fn serialized_state(&self) -> SEXP {
183        use crate::into_r::IntoR;
184        self.to_vec().into_sexp()
185    }
186
187    fn unserialize(state: SEXP) -> Option<Self> {
188        use crate::from_r::TryFromSexp;
189        Vec::<bool>::try_from_sexp(state)
190            .ok()
191            .map(|v| v.into_boxed_slice())
192    }
193}
194
195impl AltrepSerialize for Box<[String]> {
196    fn serialized_state(&self) -> SEXP {
197        use crate::into_r::IntoR;
198        self.to_vec().into_sexp()
199    }
200
201    fn unserialize(state: SEXP) -> Option<Self> {
202        use crate::from_r::TryFromSexp;
203        Vec::<String>::try_from_sexp(state)
204            .ok()
205            .map(|v| v.into_boxed_slice())
206    }
207}
208
209impl AltrepSerialize for Box<[Rcomplex]> {
210    fn serialized_state(&self) -> SEXP {
211        use crate::into_r::IntoR;
212        self.to_vec().into_sexp()
213    }
214
215    fn unserialize(state: SEXP) -> Option<Self> {
216        use crate::from_r::TryFromSexp;
217        Vec::<Rcomplex>::try_from_sexp(state)
218            .ok()
219            .map(|v| v.into_boxed_slice())
220    }
221}
222// endregion
223
224// region: Built-in implementations for Vec<T>
225
226impl_len_vec!(i32);
227
228impl AltIntegerData for Vec<i32> {
229    fn elt(&self, i: usize) -> i32 {
230        self[i]
231    }
232
233    fn as_slice(&self) -> Option<&[i32]> {
234        Some(self.as_slice())
235    }
236
237    fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
238        let end = (start + len).min(self.len());
239        let actual_len = end.saturating_sub(start);
240        if actual_len > 0 {
241            buf[..actual_len].copy_from_slice(&self[start..end]);
242        }
243        actual_len
244    }
245
246    fn no_na(&self) -> Option<bool> {
247        Some(!self.contains(&i32::MIN))
248    }
249
250    fn sum(&self, na_rm: bool) -> Option<i64> {
251        let mut sum: i64 = 0;
252        for &x in self.iter() {
253            if x == i32::MIN {
254                if !na_rm {
255                    return None; // NA propagates
256                }
257            } else {
258                sum += x as i64;
259            }
260        }
261        Some(sum)
262    }
263
264    fn min(&self, na_rm: bool) -> Option<i32> {
265        let mut min = i32::MAX;
266        let mut found = false;
267        for &x in self.iter() {
268            if x == i32::MIN {
269                if !na_rm {
270                    return None;
271                }
272            } else {
273                found = true;
274                min = min.min(x);
275            }
276        }
277        if found { Some(min) } else { None }
278    }
279
280    fn max(&self, na_rm: bool) -> Option<i32> {
281        let mut max = i32::MIN + 1; // Avoid NA sentinel
282        let mut found = false;
283        for &x in self.iter() {
284            if x == i32::MIN {
285                if !na_rm {
286                    return None;
287                }
288            } else {
289                found = true;
290                max = max.max(x);
291            }
292        }
293        if found { Some(max) } else { None }
294    }
295}
296
297impl_dataptr_vec!(i32);
298
299impl_len_vec!(f64);
300
301impl AltRealData for Vec<f64> {
302    fn elt(&self, i: usize) -> f64 {
303        self[i]
304    }
305
306    fn as_slice(&self) -> Option<&[f64]> {
307        Some(self.as_slice())
308    }
309
310    fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
311        let end = (start + len).min(self.len());
312        let actual_len = end.saturating_sub(start);
313        if actual_len > 0 {
314            buf[..actual_len].copy_from_slice(&self[start..end]);
315        }
316        actual_len
317    }
318
319    fn no_na(&self) -> Option<bool> {
320        Some(!self.iter().any(|x| x.is_nan()))
321    }
322
323    fn sum(&self, na_rm: bool) -> Option<f64> {
324        let mut sum = 0.0;
325        for &x in self.iter() {
326            if x.is_nan() {
327                if !na_rm {
328                    return Some(f64::NAN);
329                }
330            } else {
331                sum += x;
332            }
333        }
334        Some(sum)
335    }
336
337    fn min(&self, na_rm: bool) -> Option<f64> {
338        let mut min = f64::INFINITY;
339        let mut found = false;
340        for &x in self.iter() {
341            if x.is_nan() {
342                if !na_rm {
343                    return Some(f64::NAN);
344                }
345            } else {
346                found = true;
347                min = min.min(x);
348            }
349        }
350        if found { Some(min) } else { None }
351    }
352
353    fn max(&self, na_rm: bool) -> Option<f64> {
354        let mut max = f64::NEG_INFINITY;
355        let mut found = false;
356        for &x in self.iter() {
357            if x.is_nan() {
358                if !na_rm {
359                    return Some(f64::NAN);
360                }
361            } else {
362                found = true;
363                max = max.max(x);
364            }
365        }
366        if found { Some(max) } else { None }
367    }
368}
369
370impl_dataptr_vec!(f64);
371
372impl_len_vec!(u8);
373
374impl AltRawData for Vec<u8> {
375    fn elt(&self, i: usize) -> u8 {
376        self[i]
377    }
378
379    fn as_slice(&self) -> Option<&[u8]> {
380        Some(self.as_slice())
381    }
382
383    fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
384        let end = (start + len).min(self.len());
385        let actual_len = end.saturating_sub(start);
386        if actual_len > 0 {
387            buf[..actual_len].copy_from_slice(&self[start..end]);
388        }
389        actual_len
390    }
391}
392
393impl_dataptr_vec!(u8);
394
395impl_len_vec!(String);
396
397impl AltStringData for Vec<String> {
398    fn elt(&self, i: usize) -> Option<&str> {
399        Some(self[i].as_str())
400    }
401
402    fn no_na(&self) -> Option<bool> {
403        Some(true) // String vectors don't have NA
404    }
405}
406
407impl_len_vec!(Option<String>);
408
409impl AltStringData for Vec<Option<String>> {
410    fn elt(&self, i: usize) -> Option<&str> {
411        self[i].as_deref()
412    }
413
414    fn no_na(&self) -> Option<bool> {
415        Some(!self.iter().any(|x| x.is_none()))
416    }
417}
418
419impl AltrepLen for Vec<std::borrow::Cow<'static, str>> {
420    fn len(&self) -> usize {
421        self.len()
422    }
423}
424
425impl AltStringData for Vec<std::borrow::Cow<'static, str>> {
426    fn elt(&self, i: usize) -> Option<&str> {
427        Some(self[i].as_ref())
428    }
429
430    fn no_na(&self) -> Option<bool> {
431        Some(true) // Cow vectors don't have NA
432    }
433}
434
435impl AltrepLen for Vec<Option<std::borrow::Cow<'static, str>>> {
436    fn len(&self) -> usize {
437        self.len()
438    }
439}
440
441impl AltStringData for Vec<Option<std::borrow::Cow<'static, str>>> {
442    fn elt(&self, i: usize) -> Option<&str> {
443        self[i].as_deref()
444    }
445
446    fn no_na(&self) -> Option<bool> {
447        Some(!self.iter().any(|x| x.is_none()))
448    }
449}
450
451impl_len_vec!(bool);
452
453impl AltLogicalData for Vec<bool> {
454    fn elt(&self, i: usize) -> Logical {
455        if self[i] {
456            Logical::True
457        } else {
458            Logical::False
459        }
460    }
461
462    fn no_na(&self) -> Option<bool> {
463        Some(true) // bool can't be NA
464    }
465
466    fn sum(&self, _na_rm: bool) -> Option<i64> {
467        Some(self.iter().filter(|&&x| x).count() as i64)
468    }
469}
470// endregion
471
472// region: Built-in implementations for Box<[T]> (owned slices)
473// Box<[T]> is a fat pointer (Sized) that wraps a DST slice.
474// Unlike Vec<T>, it has no capacity field - just ptr + len (2 words).
475// This makes it more memory-efficient for fixed-size data.
476//
477// Box<[T]> CAN be used directly with ALTREP via the proc-macro:
478// ```
479// #[miniextendr(class = "BoxedInts")]
480// pub struct BoxedIntsClass(Box<[i32]>);
481// ```
482//
483// Or use these trait implementations in custom wrapper structs.
484
485impl_len_boxed!(i32);
486
487impl AltIntegerData for Box<[i32]> {
488    fn elt(&self, i: usize) -> i32 {
489        self[i]
490    }
491
492    fn as_slice(&self) -> Option<&[i32]> {
493        Some(self)
494    }
495
496    fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
497        let end = (start + len).min(<[i32]>::len(self));
498        let actual_len = end.saturating_sub(start);
499        if actual_len > 0 {
500            buf[..actual_len].copy_from_slice(&self[start..end]);
501        }
502        actual_len
503    }
504
505    fn no_na(&self) -> Option<bool> {
506        Some(!self.contains(&i32::MIN))
507    }
508
509    fn sum(&self, na_rm: bool) -> Option<i64> {
510        let mut sum: i64 = 0;
511        for &x in self.iter() {
512            if x == i32::MIN {
513                if !na_rm {
514                    return None;
515                }
516            } else {
517                sum += x as i64;
518            }
519        }
520        Some(sum)
521    }
522
523    fn min(&self, na_rm: bool) -> Option<i32> {
524        let mut min = i32::MAX;
525        let mut found = false;
526        for &x in self.iter() {
527            if x == i32::MIN {
528                if !na_rm {
529                    return None;
530                }
531            } else {
532                found = true;
533                min = min.min(x);
534            }
535        }
536        if found { Some(min) } else { None }
537    }
538
539    fn max(&self, na_rm: bool) -> Option<i32> {
540        let mut max = i32::MIN + 1; // i32::MIN is NA
541        let mut found = false;
542        for &x in self.iter() {
543            if x == i32::MIN {
544                if !na_rm {
545                    return None;
546                }
547            } else {
548                found = true;
549                max = max.max(x);
550            }
551        }
552        if found { Some(max) } else { None }
553    }
554}
555
556impl_dataptr_boxed!(i32);
557
558impl_len_boxed!(f64);
559
560impl AltRealData for Box<[f64]> {
561    fn elt(&self, i: usize) -> f64 {
562        self[i]
563    }
564
565    fn as_slice(&self) -> Option<&[f64]> {
566        Some(self)
567    }
568
569    fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
570        let end = (start + len).min(<[f64]>::len(self));
571        let actual_len = end.saturating_sub(start);
572        if actual_len > 0 {
573            buf[..actual_len].copy_from_slice(&self[start..end]);
574        }
575        actual_len
576    }
577
578    fn no_na(&self) -> Option<bool> {
579        Some(!self.iter().any(|x| x.is_nan()))
580    }
581
582    fn sum(&self, na_rm: bool) -> Option<f64> {
583        let mut sum = 0.0;
584        for &x in self.iter() {
585            if x.is_nan() {
586                if !na_rm {
587                    return Some(f64::NAN);
588                }
589            } else {
590                sum += x;
591            }
592        }
593        Some(sum)
594    }
595
596    fn min(&self, na_rm: bool) -> Option<f64> {
597        let mut min = f64::INFINITY;
598        let mut found = false;
599        for &x in self.iter() {
600            if x.is_nan() {
601                if !na_rm {
602                    return Some(f64::NAN);
603                }
604            } else {
605                found = true;
606                min = min.min(x);
607            }
608        }
609        if found { Some(min) } else { None }
610    }
611
612    fn max(&self, na_rm: bool) -> Option<f64> {
613        let mut max = f64::NEG_INFINITY;
614        let mut found = false;
615        for &x in self.iter() {
616            if x.is_nan() {
617                if !na_rm {
618                    return Some(f64::NAN);
619                }
620            } else {
621                found = true;
622                max = max.max(x);
623            }
624        }
625        if found { Some(max) } else { None }
626    }
627}
628
629impl_dataptr_boxed!(f64);
630
631impl_len_boxed!(u8);
632
633impl AltRawData for Box<[u8]> {
634    fn elt(&self, i: usize) -> u8 {
635        self[i]
636    }
637
638    fn as_slice(&self) -> Option<&[u8]> {
639        Some(self)
640    }
641
642    fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
643        let end = (start + len).min(<[u8]>::len(self));
644        let actual_len = end.saturating_sub(start);
645        if actual_len > 0 {
646            buf[..actual_len].copy_from_slice(&self[start..end]);
647        }
648        actual_len
649    }
650}
651
652impl_dataptr_boxed!(u8);
653
654impl_len_boxed!(bool);
655
656impl AltLogicalData for Box<[bool]> {
657    fn elt(&self, i: usize) -> Logical {
658        if self[i] {
659            Logical::True
660        } else {
661            Logical::False
662        }
663    }
664
665    fn no_na(&self) -> Option<bool> {
666        Some(true) // bool can't be NA
667    }
668
669    fn sum(&self, _na_rm: bool) -> Option<i64> {
670        Some(self.iter().filter(|&&x| x).count() as i64)
671    }
672}
673
674impl_len_boxed!(String);
675
676impl AltStringData for Box<[String]> {
677    fn elt(&self, i: usize) -> Option<&str> {
678        Some(self[i].as_str())
679    }
680
681    fn no_na(&self) -> Option<bool> {
682        Some(true) // String can't be NA
683    }
684}
685// endregion
686
687// region: AltrepSerialize implementations for Range types
688// Ranges serialize to a 2-element integer/real vector [start, end].
689
690impl AltrepSerialize for Range<i32> {
691    fn serialized_state(&self) -> SEXP {
692        use crate::into_r::IntoR;
693        vec![self.start, self.end].into_sexp()
694    }
695
696    fn unserialize(state: SEXP) -> Option<Self> {
697        use crate::from_r::TryFromSexp;
698        let v = Vec::<i32>::try_from_sexp(state).ok()?;
699        if v.len() == 2 { Some(v[0]..v[1]) } else { None }
700    }
701}
702
703impl AltrepSerialize for Range<i64> {
704    fn serialized_state(&self) -> SEXP {
705        use crate::into_r::IntoR;
706        // Store i64 bit patterns in f64 slots for lossless round-trip.
707        // Plain `as f64` loses precision for values > 2^53.
708        vec![
709            f64::from_bits(self.start as u64),
710            f64::from_bits(self.end as u64),
711        ]
712        .into_sexp()
713    }
714
715    fn unserialize(state: SEXP) -> Option<Self> {
716        use crate::from_r::TryFromSexp;
717        let v = Vec::<f64>::try_from_sexp(state).ok()?;
718        if v.len() == 2 {
719            Some((v[0].to_bits() as i64)..(v[1].to_bits() as i64))
720        } else {
721            None
722        }
723    }
724}
725
726impl AltrepSerialize for Range<f64> {
727    fn serialized_state(&self) -> SEXP {
728        use crate::into_r::IntoR;
729        vec![self.start, self.end].into_sexp()
730    }
731
732    fn unserialize(state: SEXP) -> Option<Self> {
733        use crate::from_r::TryFromSexp;
734        let v = Vec::<f64>::try_from_sexp(state).ok()?;
735        if v.len() == 2 { Some(v[0]..v[1]) } else { None }
736    }
737}
738// endregion
739
740// region: Built-in implementations for Range types
741
742impl AltrepLen for Range<i32> {
743    fn len(&self) -> usize {
744        if self.end > self.start {
745            (self.end - self.start) as usize
746        } else {
747            0
748        }
749    }
750}
751
752impl AltIntegerData for Range<i32> {
753    fn elt(&self, i: usize) -> i32 {
754        self.start + i as i32
755    }
756
757    fn is_sorted(&self) -> Option<Sortedness> {
758        Some(Sortedness::Increasing)
759    }
760
761    fn no_na(&self) -> Option<bool> {
762        // i32::MIN is NA_INTEGER in R. Check if the range contains it.
763        // Range is [start, end), so i32::MIN is included iff start <= i32::MIN < end
764        // Since start is the smallest value, we just check if start == i32::MIN
765        let contains_na = self.start == i32::MIN && self.end > i32::MIN;
766        Some(!contains_na)
767    }
768
769    fn sum(&self, na_rm: bool) -> Option<i64> {
770        let n = AltrepLen::len(self) as i64;
771        if n == 0 {
772            return Some(0);
773        }
774
775        // Check if range contains NA (i32::MIN)
776        let contains_na = self.start == i32::MIN && self.end > i32::MIN;
777        if contains_na && !na_rm {
778            return None; // NA propagates
779        }
780
781        // Sum of arithmetic sequence: n/2 * (first + last)
782        // If na_rm and contains NA, exclude the first element (i32::MIN)
783        if contains_na {
784            // Exclude first element (NA), sum from start+1 to end-1
785            let n_valid = n - 1;
786            if n_valid == 0 {
787                return Some(0);
788            }
789            let first = (self.start + 1) as i64;
790            let last = (self.end - 1) as i64;
791            Some(n_valid * (first + last) / 2)
792        } else {
793            let first = self.start as i64;
794            let last = (self.end - 1) as i64;
795            Some(n * (first + last) / 2)
796        }
797    }
798
799    fn min(&self, na_rm: bool) -> Option<i32> {
800        if AltrepLen::len(self) == 0 {
801            return None;
802        }
803
804        // Check if first element is NA
805        if self.start == i32::MIN {
806            if na_rm {
807                // Skip NA, return second element if it exists
808                if self.end > self.start + 1 {
809                    Some(self.start + 1)
810                } else {
811                    None // Only element was NA
812                }
813            } else {
814                None // NA propagates
815            }
816        } else {
817            Some(self.start)
818        }
819    }
820
821    fn max(&self, na_rm: bool) -> Option<i32> {
822        if AltrepLen::len(self) == 0 {
823            return None;
824        }
825
826        // For increasing range, max is end-1 (last element)
827        // Check if range contains NA (first element)
828        let contains_na = self.start == i32::MIN && self.end > i32::MIN;
829        if contains_na && !na_rm {
830            return None; // NA propagates
831        }
832
833        // Max is always end-1 (last element), which is not NA
834        // (NA would only be first element if start == i32::MIN)
835        Some(self.end - 1)
836    }
837}
838
839impl AltrepLen for Range<i64> {
840    fn len(&self) -> usize {
841        if self.end > self.start {
842            (self.end - self.start) as usize
843        } else {
844            0
845        }
846    }
847}
848
849impl AltIntegerData for Range<i64> {
850    fn elt(&self, i: usize) -> i32 {
851        let val = self.start.saturating_add(i as i64);
852        // Bounds check: return NA_INTEGER for values outside i32 range
853        // Also, i32::MIN is the NA sentinel, so values equal to it are NA
854        if val > i32::MAX as i64 || val <= i32::MIN as i64 {
855            crate::altrep_traits::NA_INTEGER
856        } else {
857            val as i32
858        }
859    }
860
861    fn is_sorted(&self) -> Option<Sortedness> {
862        Some(Sortedness::Increasing)
863    }
864
865    fn no_na(&self) -> Option<bool> {
866        // An element is NA if:
867        // 1. It's outside valid i32 range (< i32::MIN or > i32::MAX)
868        // 2. It equals i32::MIN (NA sentinel)
869        //
870        // For increasing range [start, end), elements range from start to end-1.
871        // Range contains NA if:
872        // - start <= i32::MIN as i64 (NA sentinel could be in range)
873        // - OR end > i32::MAX as i64 + 1 (values exceed i32::MAX)
874        // - OR start < i32::MIN as i64 (values below i32 range)
875        let na_sentinel = i32::MIN as i64;
876        let i32_max = i32::MAX as i64;
877
878        // Check if NA sentinel is in [start, end)
879        let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
880
881        // Check if any values are outside valid i32 range
882        // Valid range for ALTREP integers: (i32::MIN, i32::MAX] (excluding NA sentinel)
883        let has_underflow = self.start < na_sentinel;
884        let has_overflow = (self.end - 1) > i32_max;
885
886        Some(!contains_na_sentinel && !has_underflow && !has_overflow)
887    }
888
889    fn sum(&self, na_rm: bool) -> Option<i64> {
890        let n = AltrepLen::len(self) as i64;
891        if n == 0 {
892            return Some(0);
893        }
894
895        // Check if range contains any NA values
896        let na_sentinel = i32::MIN as i64;
897        let i32_max = i32::MAX as i64;
898        let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
899        let has_underflow = self.start < na_sentinel;
900        let has_overflow = (self.end - 1) > i32_max;
901        let has_na = contains_na_sentinel || has_underflow || has_overflow;
902
903        if has_na && !na_rm {
904            return None; // NA propagates
905        }
906
907        if has_na {
908            // When na_rm=true, we need to exclude NA values
909            // This is complex for ranges with out-of-bounds values, so let R compute
910            return None;
911        }
912
913        let first = self.start;
914        let last = self.end - 1;
915
916        // Use checked arithmetic to detect overflow
917        // Formula: n * (first + last) / 2
918        let sum_endpoints = first.checked_add(last)?;
919        let product = n.checked_mul(sum_endpoints)?;
920        Some(product / 2)
921    }
922
923    fn min(&self, na_rm: bool) -> Option<i32> {
924        if AltrepLen::len(self) == 0 {
925            return None;
926        }
927
928        let na_sentinel = i32::MIN as i64;
929        let i32_max = i32::MAX as i64;
930
931        // Check for NA conditions
932        let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
933        let has_underflow = self.start < na_sentinel;
934        let has_overflow = (self.end - 1) > i32_max;
935        let has_na = contains_na_sentinel || has_underflow || has_overflow;
936
937        if has_na && !na_rm {
938            return None; // NA propagates
939        }
940
941        if has_na {
942            // Complex case: need to find first non-NA value
943            // Let R compute this
944            return None;
945        }
946
947        // No NA, return start (which is within valid i32 range)
948        Some(self.start as i32)
949    }
950
951    fn max(&self, na_rm: bool) -> Option<i32> {
952        if AltrepLen::len(self) == 0 {
953            return None;
954        }
955
956        let na_sentinel = i32::MIN as i64;
957        let i32_max = i32::MAX as i64;
958
959        // Check for NA conditions
960        let contains_na_sentinel = self.start <= na_sentinel && self.end > na_sentinel;
961        let has_underflow = self.start < na_sentinel;
962        let has_overflow = (self.end - 1) > i32_max;
963        let has_na = contains_na_sentinel || has_underflow || has_overflow;
964
965        if has_na && !na_rm {
966            return None; // NA propagates
967        }
968
969        if has_na {
970            // Complex case: need to find last non-NA value
971            // Let R compute this
972            return None;
973        }
974
975        // No NA, return end-1 (which is within valid i32 range)
976        Some((self.end - 1) as i32)
977    }
978}
979
980impl AltrepLen for Range<f64> {
981    fn len(&self) -> usize {
982        // For f64 ranges, assume step of 1.0
983        if self.end > self.start {
984            (self.end - self.start).ceil() as usize
985        } else {
986            0
987        }
988    }
989}
990
991impl AltRealData for Range<f64> {
992    fn elt(&self, i: usize) -> f64 {
993        self.start + i as f64
994    }
995
996    fn is_sorted(&self) -> Option<Sortedness> {
997        Some(Sortedness::Increasing)
998    }
999
1000    fn no_na(&self) -> Option<bool> {
1001        Some(true)
1002    }
1003
1004    fn sum(&self, _na_rm: bool) -> Option<f64> {
1005        let n = AltrepLen::len(self) as f64;
1006        if n == 0.0 {
1007            return Some(0.0);
1008        }
1009        let first = self.start;
1010        let last = self.start + (n - 1.0);
1011        Some(n * (first + last) / 2.0)
1012    }
1013
1014    fn min(&self, _na_rm: bool) -> Option<f64> {
1015        if AltrepLen::len(self) > 0 {
1016            Some(self.start)
1017        } else {
1018            None
1019        }
1020    }
1021
1022    fn max(&self, _na_rm: bool) -> Option<f64> {
1023        if AltrepLen::len(self) > 0 {
1024            Some(self.start + (AltrepLen::len(self) - 1) as f64)
1025        } else {
1026            None
1027        }
1028    }
1029}
1030// endregion
1031
1032// region: Built-in implementations for slices (read-only)
1033
1034impl_len_slice!(i32);
1035
1036impl AltIntegerData for &[i32] {
1037    fn elt(&self, i: usize) -> i32 {
1038        self[i]
1039    }
1040
1041    fn as_slice(&self) -> Option<&[i32]> {
1042        Some(self)
1043    }
1044
1045    fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
1046        let end = (start + len).min(<[i32]>::len(self));
1047        let actual_len = end.saturating_sub(start);
1048        if actual_len > 0 {
1049            buf[..actual_len].copy_from_slice(&self[start..end]);
1050        }
1051        actual_len
1052    }
1053
1054    fn no_na(&self) -> Option<bool> {
1055        // i32 slices have NA as i32::MIN
1056        Some(!self.contains(&i32::MIN))
1057    }
1058
1059    fn sum(&self, _na_rm: bool) -> Option<i64> {
1060        // Check for NA (i32::MIN)
1061        if self.contains(&i32::MIN) {
1062            if _na_rm {
1063                Some(
1064                    self.iter()
1065                        .filter(|&&x| x != i32::MIN)
1066                        .map(|&x| x as i64)
1067                        .sum(),
1068                )
1069            } else {
1070                None // Return NA
1071            }
1072        } else {
1073            Some(self.iter().map(|&x| x as i64).sum())
1074        }
1075    }
1076
1077    fn min(&self, _na_rm: bool) -> Option<i32> {
1078        if self.is_empty() {
1079            return None;
1080        }
1081        if _na_rm {
1082            self.iter().filter(|&&x| x != i32::MIN).copied().min()
1083        } else if self.contains(&i32::MIN) {
1084            None // NA present
1085        } else {
1086            self.iter().copied().min()
1087        }
1088    }
1089
1090    fn max(&self, _na_rm: bool) -> Option<i32> {
1091        if self.is_empty() {
1092            return None;
1093        }
1094        if _na_rm {
1095            self.iter().filter(|&&x| x != i32::MIN).copied().max()
1096        } else if self.contains(&i32::MIN) {
1097            None // NA present
1098        } else {
1099            self.iter().copied().max()
1100        }
1101    }
1102}
1103
1104impl_len_slice!(f64);
1105
1106impl AltRealData for &[f64] {
1107    fn elt(&self, i: usize) -> f64 {
1108        self[i]
1109    }
1110
1111    fn as_slice(&self) -> Option<&[f64]> {
1112        Some(self)
1113    }
1114
1115    fn no_na(&self) -> Option<bool> {
1116        Some(!self.iter().any(|x| x.is_nan()))
1117    }
1118
1119    fn sum(&self, na_rm: bool) -> Option<f64> {
1120        if na_rm {
1121            Some(self.iter().filter(|x| !x.is_nan()).sum())
1122        } else if self.iter().any(|x| x.is_nan()) {
1123            None // Return NA
1124        } else {
1125            Some(self.iter().sum())
1126        }
1127    }
1128
1129    fn min(&self, na_rm: bool) -> Option<f64> {
1130        if self.is_empty() {
1131            return None;
1132        }
1133        if na_rm {
1134            self.iter()
1135                .filter(|x| !x.is_nan())
1136                .copied()
1137                .min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
1138        } else if self.iter().any(|x| x.is_nan()) {
1139            None
1140        } else {
1141            self.iter()
1142                .copied()
1143                .min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
1144        }
1145    }
1146
1147    fn max(&self, na_rm: bool) -> Option<f64> {
1148        if self.is_empty() {
1149            return None;
1150        }
1151        if na_rm {
1152            self.iter()
1153                .filter(|x| !x.is_nan())
1154                .copied()
1155                .max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
1156        } else if self.iter().any(|x| x.is_nan()) {
1157            None
1158        } else {
1159            self.iter()
1160                .copied()
1161                .max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
1162        }
1163    }
1164}
1165
1166impl_len_slice!(u8);
1167
1168impl AltRawData for &[u8] {
1169    fn elt(&self, i: usize) -> u8 {
1170        self[i]
1171    }
1172
1173    fn as_slice(&self) -> Option<&[u8]> {
1174        Some(self)
1175    }
1176}
1177
1178impl_len_slice!(bool);
1179
1180impl AltLogicalData for &[bool] {
1181    fn elt(&self, i: usize) -> Logical {
1182        Logical::from_bool(self[i])
1183    }
1184
1185    fn no_na(&self) -> Option<bool> {
1186        Some(true) // bool can't be NA
1187    }
1188
1189    fn sum(&self, _na_rm: bool) -> Option<i64> {
1190        Some(self.iter().filter(|&&x| x).count() as i64)
1191    }
1192}
1193
1194impl_len_slice!(String);
1195
1196impl AltStringData for &[String] {
1197    fn elt(&self, i: usize) -> Option<&str> {
1198        Some(self[i].as_str())
1199    }
1200}
1201
1202impl_len_slice!(&str);
1203
1204impl AltStringData for &[&str] {
1205    fn elt(&self, i: usize) -> Option<&str> {
1206        Some(self[i])
1207    }
1208}
1209// endregion
1210
1211// region: NOTE on &'static [T] (static slices)
1212//
1213// `&'static [T]` is Sized (fat pointer: ptr + len) and satisfies 'static,
1214// so it can be used DIRECTLY with ALTREP via ExternalPtr.
1215//
1216// The data trait implementations above for `&[T]` already cover `&'static [T]`
1217// since `&'static [T]` is a subtype of `&[T]`. The ALTREP trait implementations
1218// (Altrep, AltVec, AltInteger, etc.) are provided separately in altrep_impl.rs.
1219//
1220// Use cases:
1221// - Const arrays: `static DATA: [i32; 5] = [1, 2, 3, 4, 5]; create_altrep(&DATA[..])`
1222// - Leaked data: `let s: &'static [i32] = Box::leak(vec.into_boxed_slice());`
1223// - Memory-mapped files with 'static lifetime
1224// endregion
1225
1226// region: Built-in implementations for arrays (owned, fixed-size)
1227
1228impl_len_array!(i32);
1229
1230impl<const N: usize> AltIntegerData for [i32; N] {
1231    fn elt(&self, i: usize) -> i32 {
1232        self[i]
1233    }
1234
1235    fn as_slice(&self) -> Option<&[i32]> {
1236        Some(self.as_slice())
1237    }
1238
1239    fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
1240        let end = (start + len).min(N);
1241        let actual_len = end.saturating_sub(start);
1242        if actual_len > 0 {
1243            buf[..actual_len].copy_from_slice(&self[start..end]);
1244        }
1245        actual_len
1246    }
1247
1248    fn no_na(&self) -> Option<bool> {
1249        Some(!self.contains(&i32::MIN))
1250    }
1251}
1252
1253impl_len_array!(f64);
1254
1255impl<const N: usize> AltRealData for [f64; N] {
1256    fn elt(&self, i: usize) -> f64 {
1257        self[i]
1258    }
1259
1260    fn as_slice(&self) -> Option<&[f64]> {
1261        Some(self.as_slice())
1262    }
1263
1264    fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
1265        let end = (start + len).min(N);
1266        let actual_len = end.saturating_sub(start);
1267        if actual_len > 0 {
1268            buf[..actual_len].copy_from_slice(&self[start..end]);
1269        }
1270        actual_len
1271    }
1272
1273    fn no_na(&self) -> Option<bool> {
1274        Some(!self.iter().any(|x| x.is_nan()))
1275    }
1276}
1277
1278impl_len_array!(bool);
1279
1280impl<const N: usize> AltLogicalData for [bool; N] {
1281    fn elt(&self, i: usize) -> Logical {
1282        Logical::from_bool(self[i])
1283    }
1284
1285    fn no_na(&self) -> Option<bool> {
1286        Some(true) // bool arrays can't have NA
1287    }
1288}
1289
1290impl_len_array!(u8);
1291
1292impl<const N: usize> AltRawData for [u8; N] {
1293    fn elt(&self, i: usize) -> u8 {
1294        self[i]
1295    }
1296
1297    fn as_slice(&self) -> Option<&[u8]> {
1298        Some(self.as_slice())
1299    }
1300
1301    fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
1302        let end = (start + len).min(N);
1303        let actual_len = end.saturating_sub(start);
1304        if actual_len > 0 {
1305            buf[..actual_len].copy_from_slice(&self[start..end]);
1306        }
1307        actual_len
1308    }
1309}
1310
1311impl_len_array!(String);
1312
1313impl<const N: usize> AltStringData for [String; N] {
1314    fn elt(&self, i: usize) -> Option<&str> {
1315        Some(self[i].as_str())
1316    }
1317}
1318// endregion
1319
1320// region: Built-in implementations for Vec<Rcomplex> (complex numbers)
1321
1322impl_len_vec!(Rcomplex);
1323
1324impl AltComplexData for Vec<Rcomplex> {
1325    fn elt(&self, i: usize) -> Rcomplex {
1326        self[i]
1327    }
1328
1329    fn as_slice(&self) -> Option<&[Rcomplex]> {
1330        Some(self.as_slice())
1331    }
1332
1333    fn get_region(&self, start: usize, len: usize, buf: &mut [Rcomplex]) -> usize {
1334        let end = (start + len).min(self.len());
1335        let actual_len = end.saturating_sub(start);
1336        if actual_len > 0 {
1337            buf[..actual_len].copy_from_slice(&self[start..end]);
1338        }
1339        actual_len
1340    }
1341}
1342
1343impl_dataptr_vec!(Rcomplex);
1344// endregion
1345
1346// region: Built-in implementations for Box<[Rcomplex]>
1347
1348impl_len_boxed!(Rcomplex);
1349
1350impl AltComplexData for Box<[Rcomplex]> {
1351    fn elt(&self, i: usize) -> Rcomplex {
1352        self[i]
1353    }
1354
1355    fn as_slice(&self) -> Option<&[Rcomplex]> {
1356        Some(self.as_ref())
1357    }
1358
1359    fn get_region(&self, start: usize, len: usize, buf: &mut [Rcomplex]) -> usize {
1360        let end = (start + len).min(self.len());
1361        let actual_len = end.saturating_sub(start);
1362        if actual_len > 0 {
1363            buf[..actual_len].copy_from_slice(&self[start..end]);
1364        }
1365        actual_len
1366    }
1367}
1368
1369impl_dataptr_boxed!(Rcomplex);
1370// endregion
1371
1372// region: Built-in implementations for [Rcomplex; N] (complex arrays)
1373
1374impl_len_array!(Rcomplex);
1375
1376impl<const N: usize> AltComplexData for [Rcomplex; N] {
1377    fn elt(&self, i: usize) -> Rcomplex {
1378        self[i]
1379    }
1380
1381    fn as_slice(&self) -> Option<&[Rcomplex]> {
1382        Some(self.as_slice())
1383    }
1384
1385    fn get_region(&self, start: usize, len: usize, buf: &mut [Rcomplex]) -> usize {
1386        let end = (start + len).min(N);
1387        let actual_len = end.saturating_sub(start);
1388        if actual_len > 0 {
1389            buf[..actual_len].copy_from_slice(&self[start..end]);
1390        }
1391        actual_len
1392    }
1393}
1394// endregion
1395
1396// region: Built-in implementations for Cow<'static, [T]>
1397//
1398// Cow<'static, [T]> enables zero-copy borrows from R vectors while retaining
1399// ownership semantics. Borrowed variants expose the underlying R data directly
1400// via dataptr; Owned variants behave like Vec<T>. Copy-on-write happens
1401// automatically when R requests a writable dataptr on a Borrowed variant.
1402
1403use std::borrow::Cow;
1404
1405macro_rules! impl_len_cow {
1406    ($elem:ty) => {
1407        impl AltrepLen for Cow<'static, [$elem]> {
1408            fn len(&self) -> usize {
1409                <[$elem]>::len(self)
1410            }
1411        }
1412    };
1413}
1414
1415macro_rules! impl_dataptr_cow {
1416    ($elem:ty) => {
1417        impl AltrepDataptr<$elem> for Cow<'static, [$elem]> {
1418            fn dataptr(&mut self, writable: bool) -> Option<*mut $elem> {
1419                if writable {
1420                    // to_mut() triggers copy-on-write for Borrowed variants.
1421                    // Only do this when R intends to write through the pointer.
1422                    Some(self.to_mut().as_mut_ptr())
1423                } else {
1424                    // Read-only access: return the existing pointer without
1425                    // forcing a copy for Borrowed variants.
1426                    Some(self.as_ptr().cast_mut())
1427                }
1428            }
1429
1430            fn dataptr_or_null(&self) -> Option<*const $elem> {
1431                Some(self.as_ptr())
1432            }
1433        }
1434    };
1435}
1436
1437macro_rules! impl_serialize_cow {
1438    ($elem:ty) => {
1439        impl AltrepSerialize for Cow<'static, [$elem]> {
1440            fn serialized_state(&self) -> SEXP {
1441                use crate::into_r::IntoR;
1442                self.clone().into_sexp()
1443            }
1444
1445            fn unserialize(state: SEXP) -> Option<Self> {
1446                use crate::from_r::TryFromSexp;
1447                Cow::<'static, [$elem]>::try_from_sexp(state).ok()
1448            }
1449        }
1450    };
1451}
1452
1453impl_len_cow!(i32);
1454
1455impl AltIntegerData for Cow<'static, [i32]> {
1456    fn elt(&self, i: usize) -> i32 {
1457        self[i]
1458    }
1459
1460    fn as_slice(&self) -> Option<&[i32]> {
1461        Some(self.as_ref())
1462    }
1463
1464    fn get_region(&self, start: usize, len: usize, buf: &mut [i32]) -> usize {
1465        let end = (start + len).min(<[i32]>::len(self));
1466        let actual_len = end.saturating_sub(start);
1467        if actual_len > 0 {
1468            buf[..actual_len].copy_from_slice(&self[start..end]);
1469        }
1470        actual_len
1471    }
1472
1473    fn no_na(&self) -> Option<bool> {
1474        Some(!self.contains(&i32::MIN))
1475    }
1476
1477    fn sum(&self, na_rm: bool) -> Option<i64> {
1478        let mut sum: i64 = 0;
1479        for &x in self.iter() {
1480            if x == i32::MIN {
1481                if !na_rm {
1482                    return None;
1483                }
1484            } else {
1485                sum += x as i64;
1486            }
1487        }
1488        Some(sum)
1489    }
1490
1491    fn min(&self, na_rm: bool) -> Option<i32> {
1492        let mut min = i32::MAX;
1493        let mut found = false;
1494        for &x in self.iter() {
1495            if x == i32::MIN {
1496                if !na_rm {
1497                    return None;
1498                }
1499            } else {
1500                found = true;
1501                min = min.min(x);
1502            }
1503        }
1504        if found { Some(min) } else { None }
1505    }
1506
1507    fn max(&self, na_rm: bool) -> Option<i32> {
1508        let mut max = i32::MIN + 1;
1509        let mut found = false;
1510        for &x in self.iter() {
1511            if x == i32::MIN {
1512                if !na_rm {
1513                    return None;
1514                }
1515            } else {
1516                found = true;
1517                max = max.max(x);
1518            }
1519        }
1520        if found { Some(max) } else { None }
1521    }
1522}
1523
1524impl_dataptr_cow!(i32);
1525impl_serialize_cow!(i32);
1526
1527impl_len_cow!(f64);
1528
1529impl AltRealData for Cow<'static, [f64]> {
1530    fn elt(&self, i: usize) -> f64 {
1531        self[i]
1532    }
1533
1534    fn as_slice(&self) -> Option<&[f64]> {
1535        Some(self.as_ref())
1536    }
1537
1538    fn get_region(&self, start: usize, len: usize, buf: &mut [f64]) -> usize {
1539        let end = (start + len).min(<[f64]>::len(self));
1540        let actual_len = end.saturating_sub(start);
1541        if actual_len > 0 {
1542            buf[..actual_len].copy_from_slice(&self[start..end]);
1543        }
1544        actual_len
1545    }
1546
1547    fn no_na(&self) -> Option<bool> {
1548        Some(!self.iter().any(|x| x.is_nan()))
1549    }
1550
1551    fn sum(&self, na_rm: bool) -> Option<f64> {
1552        let mut sum = 0.0;
1553        for &x in self.iter() {
1554            if x.is_nan() {
1555                if !na_rm {
1556                    return Some(f64::NAN);
1557                }
1558            } else {
1559                sum += x;
1560            }
1561        }
1562        Some(sum)
1563    }
1564
1565    fn min(&self, na_rm: bool) -> Option<f64> {
1566        let mut min = f64::INFINITY;
1567        let mut found = false;
1568        for &x in self.iter() {
1569            if x.is_nan() {
1570                if !na_rm {
1571                    return Some(f64::NAN);
1572                }
1573            } else {
1574                found = true;
1575                min = min.min(x);
1576            }
1577        }
1578        if found { Some(min) } else { None }
1579    }
1580
1581    fn max(&self, na_rm: bool) -> Option<f64> {
1582        let mut max = f64::NEG_INFINITY;
1583        let mut found = false;
1584        for &x in self.iter() {
1585            if x.is_nan() {
1586                if !na_rm {
1587                    return Some(f64::NAN);
1588                }
1589            } else {
1590                found = true;
1591                max = max.max(x);
1592            }
1593        }
1594        if found { Some(max) } else { None }
1595    }
1596}
1597
1598impl_dataptr_cow!(f64);
1599impl_serialize_cow!(f64);
1600
1601impl_len_cow!(u8);
1602
1603impl AltRawData for Cow<'static, [u8]> {
1604    fn elt(&self, i: usize) -> u8 {
1605        self[i]
1606    }
1607
1608    fn as_slice(&self) -> Option<&[u8]> {
1609        Some(self.as_ref())
1610    }
1611
1612    fn get_region(&self, start: usize, len: usize, buf: &mut [u8]) -> usize {
1613        let end = (start + len).min(<[u8]>::len(self));
1614        let actual_len = end.saturating_sub(start);
1615        if actual_len > 0 {
1616            buf[..actual_len].copy_from_slice(&self[start..end]);
1617        }
1618        actual_len
1619    }
1620}
1621
1622impl_dataptr_cow!(u8);
1623impl_serialize_cow!(u8);
1624
1625impl_len_cow!(Rcomplex);
1626
1627impl AltComplexData for Cow<'static, [Rcomplex]> {
1628    fn elt(&self, i: usize) -> Rcomplex {
1629        self[i]
1630    }
1631
1632    fn as_slice(&self) -> Option<&[Rcomplex]> {
1633        Some(self.as_ref())
1634    }
1635
1636    fn get_region(&self, start: usize, len: usize, buf: &mut [Rcomplex]) -> usize {
1637        let end = (start + len).min(<[Rcomplex]>::len(self));
1638        let actual_len = end.saturating_sub(start);
1639        if actual_len > 0 {
1640            buf[..actual_len].copy_from_slice(&self[start..end]);
1641        }
1642        actual_len
1643    }
1644}
1645
1646impl_dataptr_cow!(Rcomplex);
1647impl_serialize_cow!(Rcomplex);
1648// endregion
1649
1650// region: Low-level ALTREP trait implementations
1651//
1652// The low-level trait impls (Altrep, AltVec, Alt*, InferBase) for builtin types
1653// are located in altrep_impl.rs. This is because the impl_alt*_from_data! macros
1654// are defined there and need to be in the same module.
1655//
1656// See altrep_impl.rs for:
1657// - Vec<i32>, Vec<f64>, Vec<bool>, Vec<u8>, Vec<String>, Vec<Rcomplex>
1658// - Box<[i32]>, Box<[f64]>, Box<[bool]>, Box<[u8]>, Box<[String]>, Box<[Rcomplex]>
1659// - Cow<'static, [i32]>, Cow<'static, [f64]>, Cow<'static, [u8]>, Cow<'static, [Rcomplex]>
1660// - Range<i32>, Range<i64>, Range<f64>
1661// endregion