miniextendr_api/altrep_data/
deque.rs1use std::collections::VecDeque;
8
9use super::{
10 AltComplexData, AltIntegerData, AltRawData, AltRealData, AltrepDataptr, AltrepLen,
11 AltrepSerialize,
12};
13use crate::{IntoR, Rcomplex, SEXP, TryFromSexp};
14
15impl<T> AltrepLen for VecDeque<T> {
16 fn altrep_len(&self) -> usize {
17 VecDeque::len(self)
18 }
19}
20
21fn contiguous_slice<T>(values: &VecDeque<T>) -> Option<&[T]> {
23 let (front, back) = values.as_slices();
24 if back.is_empty() {
25 Some(front)
26 } else if front.is_empty() {
27 Some(back)
28 } else {
29 None
30 }
31}
32
33fn copy_region<T: Copy>(values: &VecDeque<T>, start: usize, len: usize, out: &mut [T]) -> usize {
35 let n = len.min(out.len()).min(values.len().saturating_sub(start));
36 if n == 0 {
37 return 0;
38 }
39 let (front, back) = values.as_slices();
40 let first = n.min(front.len().saturating_sub(start));
41 if first != 0 {
42 out[..first].copy_from_slice(&front[start..start + first]);
43 }
44 if first != n {
45 let offset = start.saturating_sub(front.len());
46 out[first..n].copy_from_slice(&back[offset..offset + n - first]);
47 }
48 n
49}
50
51macro_rules! impl_native_deque {
52 ($elem:ty, $family:ident) => {
53 impl $family for VecDeque<$elem> {
54 fn elt(&self, i: usize) -> $elem {
55 self[i]
56 }
57
58 fn as_slice(&self) -> Option<&[$elem]> {
59 contiguous_slice(self)
60 }
61
62 fn get_region(&self, start: usize, len: usize, out: &mut [$elem]) -> usize {
63 copy_region(self, start, len, out)
64 }
65 }
66
67 impl AltrepDataptr<$elem> for VecDeque<$elem> {
68 fn dataptr(&mut self, _writable: bool) -> Option<*mut $elem> {
69 Some(self.make_contiguous().as_mut_ptr())
70 }
71
72 fn dataptr_or_null(&self) -> Option<*const $elem> {
73 contiguous_slice(self).map(<[$elem]>::as_ptr)
74 }
75 }
76
77 impl AltrepSerialize for VecDeque<$elem> {
78 fn serialized_state(&self) -> SEXP {
79 self.clone().into_sexp()
80 }
81
82 fn unserialize(state: SEXP) -> Option<Self> {
83 Self::try_from_sexp(state).ok()
84 }
85 }
86 };
87}
88
89impl AltIntegerData for VecDeque<i32> {
fn elt(&self, i: usize) -> i32 { self[i] }
fn as_slice(&self) -> Option<&[i32]> { contiguous_slice(self) }
fn get_region(&self, start: usize, len: usize, out: &mut [i32]) -> usize {
copy_region(self, start, len, out)
}
}
impl AltrepDataptr<i32> for VecDeque<i32> {
fn dataptr(&mut self, _writable: bool) -> Option<*mut i32> {
Some(self.make_contiguous().as_mut_ptr())
}
fn dataptr_or_null(&self) -> Option<*const i32> {
contiguous_slice(self).map(<[i32]>::as_ptr)
}
}
impl AltrepSerialize for VecDeque<i32> {
fn serialized_state(&self) -> SEXP { self.clone().into_sexp() }
fn unserialize(state: SEXP) -> Option<Self> {
Self::try_from_sexp(state).ok()
}
}impl_native_deque!(i32, AltIntegerData);
90impl AltRealData for VecDeque<f64> {
fn elt(&self, i: usize) -> f64 { self[i] }
fn as_slice(&self) -> Option<&[f64]> { contiguous_slice(self) }
fn get_region(&self, start: usize, len: usize, out: &mut [f64]) -> usize {
copy_region(self, start, len, out)
}
}
impl AltrepDataptr<f64> for VecDeque<f64> {
fn dataptr(&mut self, _writable: bool) -> Option<*mut f64> {
Some(self.make_contiguous().as_mut_ptr())
}
fn dataptr_or_null(&self) -> Option<*const f64> {
contiguous_slice(self).map(<[f64]>::as_ptr)
}
}
impl AltrepSerialize for VecDeque<f64> {
fn serialized_state(&self) -> SEXP { self.clone().into_sexp() }
fn unserialize(state: SEXP) -> Option<Self> {
Self::try_from_sexp(state).ok()
}
}impl_native_deque!(f64, AltRealData);
91impl AltRawData for VecDeque<u8> {
fn elt(&self, i: usize) -> u8 { self[i] }
fn as_slice(&self) -> Option<&[u8]> { contiguous_slice(self) }
fn get_region(&self, start: usize, len: usize, out: &mut [u8]) -> usize {
copy_region(self, start, len, out)
}
}
impl AltrepDataptr<u8> for VecDeque<u8> {
fn dataptr(&mut self, _writable: bool) -> Option<*mut u8> {
Some(self.make_contiguous().as_mut_ptr())
}
fn dataptr_or_null(&self) -> Option<*const u8> {
contiguous_slice(self).map(<[u8]>::as_ptr)
}
}
impl AltrepSerialize for VecDeque<u8> {
fn serialized_state(&self) -> SEXP { self.clone().into_sexp() }
fn unserialize(state: SEXP) -> Option<Self> {
Self::try_from_sexp(state).ok()
}
}impl_native_deque!(u8, AltRawData);
92impl AltComplexData for VecDeque<Rcomplex> {
fn elt(&self, i: usize) -> Rcomplex { self[i] }
fn as_slice(&self) -> Option<&[Rcomplex]> { contiguous_slice(self) }
fn get_region(&self, start: usize, len: usize, out: &mut [Rcomplex])
-> usize {
copy_region(self, start, len, out)
}
}
impl AltrepDataptr<Rcomplex> for VecDeque<Rcomplex> {
fn dataptr(&mut self, _writable: bool) -> Option<*mut Rcomplex> {
Some(self.make_contiguous().as_mut_ptr())
}
fn dataptr_or_null(&self) -> Option<*const Rcomplex> {
contiguous_slice(self).map(<[Rcomplex]>::as_ptr)
}
}
impl AltrepSerialize for VecDeque<Rcomplex> {
fn serialized_state(&self) -> SEXP { self.clone().into_sexp() }
fn unserialize(state: SEXP) -> Option<Self> {
Self::try_from_sexp(state).ok()
}
}impl_native_deque!(Rcomplex, AltComplexData);
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn regions_cross_the_ring_boundary_without_rearranging_storage() {
100 let mut values = VecDeque::from(vec![0, 1, 2, 3, 4, 5, 6, 7]);
101 values.rotate_left(3);
102 let split = values.as_slices().0.len();
103 assert!(split > 0 && split < values.len());
104 let expected = values.iter().copied().collect::<Vec<_>>();
105 for start in 0..=values.len() + 1 {
106 for requested in [0, 1, 3, 8, usize::MAX] {
107 let mut out = [-1; 4];
108 let n = copy_region(&values, start, requested, &mut out);
109 let want = expected
110 .iter()
111 .skip(start)
112 .take(requested)
113 .take(4)
114 .copied()
115 .collect::<Vec<_>>();
116 assert_eq!(&out[..n], want.as_slice());
117 assert!(out[n..].iter().all(|&x| x == -1));
118 assert_eq!(values.as_slices().0.len(), split);
119 }
120 }
121 assert_eq!(copy_region(&values, usize::MAX, usize::MAX, &mut [0; 4]), 0);
122 assert_eq!(copy_region(&values, 0, 4, &mut []), 0);
123 assert_eq!(copy_region(&VecDeque::<i32>::new(), 0, 4, &mut [0; 4]), 0);
124 }
125
126 #[test]
127 fn pointer_access_makes_the_existing_owner_contiguous() {
128 let mut values = VecDeque::from(vec![1, 2, 3, 4]);
129 values.rotate_left(1);
130 assert!(AltrepDataptr::dataptr_or_null(&values).is_none());
131 let pointer = AltrepDataptr::dataptr(&mut values, true).unwrap();
132 unsafe { *pointer = 90 };
133 assert_eq!(values.iter().copied().collect::<Vec<_>>(), [90, 3, 4, 1]);
134 assert_eq!(values.as_slices().1.len(), 0);
135 assert_eq!(
136 AltrepDataptr::dataptr_or_null(&values),
137 Some(pointer.cast_const())
138 );
139 }
140}