foreign/impl/
slice.rs

1use std::ffi::c_void;
2use std::mem;
3
4use crate::foreign::*;
5
6impl<T> FreeForeign for [T]
7where
8    T: FixedAlloc,
9{
10    type Foreign = T::Foreign;
11
12    unsafe fn free_foreign(ptr: *mut Self::Foreign) {
13        libc::free(ptr.cast::<c_void>());
14    }
15}
16
17impl<T> CloneToForeign for [T]
18where
19    T: FixedAlloc,
20{
21    fn clone_to_foreign(&self) -> OwnedPointer<Self> {
22        // SAFETY: self.as_ptr() is guaranteed to point to the same number of bytes
23        // as the freshly allocated destination
24        unsafe {
25            let size = mem::size_of::<Self::Foreign>();
26            let p = libc::malloc(self.len() * size).cast::<Self::Foreign>();
27            T::clone_from_native_slice(p, self);
28            OwnedPointer::new(p)
29        }
30    }
31}
32
33impl<'a, T> BorrowForeign<'a> for [T]
34where
35    T: FixedAlloc + FreeForeign<Foreign = T> + BorrowForeign<'a, Foreign = T, Storage = &'a T> + 'a,
36{
37    type Storage = &'a Self;
38
39    fn borrow_foreign(&self) -> BorrowedPointer<Self, &Self> {
40        // SAFETY: data behind a shared reference cannot move
41        // as long as the reference is alive
42        unsafe { BorrowedPointer::new(self.as_ptr(), self) }
43    }
44}
45
46impl<'a, T> BorrowForeignMut<'a> for [T]
47where
48    T: FixedAlloc
49        + FreeForeign<Foreign = T>
50        + BorrowForeignMut<'a, Foreign = T, Storage = &'a mut T>
51        + 'a,
52{
53    type Storage = &'a mut Self;
54
55    fn borrow_foreign_mut(&mut self) -> BorrowedMutPointer<Self, &mut Self> {
56        // SAFETY: the data behind the reference will not move as
57        // long as the reference is alive
58        unsafe { BorrowedMutPointer::new(self.as_mut_ptr(), self) }
59    }
60}
61
62impl<T, const N: usize> FreeForeign for [T; N]
63where
64    T: FixedAlloc,
65{
66    type Foreign = T::Foreign;
67
68    unsafe fn free_foreign(ptr: *mut Self::Foreign) {
69        libc::free(ptr.cast::<c_void>());
70    }
71}
72
73impl<T, const N: usize> CloneToForeign for [T; N]
74where
75    T: FixedAlloc,
76{
77    fn clone_to_foreign(&self) -> OwnedPointer<Self> {
78        self[..].clone_to_foreign().into()
79    }
80}
81
82impl<T, const N: usize> FromForeign for [T; N]
83where
84    T: FixedAlloc,
85{
86    unsafe fn cloned_from_foreign(src: *const Self::Foreign) -> Self {
87        T::clone_array_from_foreign(src)
88    }
89}
90
91impl<'a, T, const N: usize> BorrowForeign<'a> for [T; N]
92where
93    T: FixedAlloc + BorrowForeign<'a, Foreign = T, Storage = &'a T> + 'a,
94{
95    type Storage = &'a [T; N];
96
97    fn borrow_foreign(&'a self) -> BorrowedPointer<Self, &'a Self> {
98        // SAFETY: data behind a shared reference cannot move
99        // as long as the reference is alive
100        unsafe { BorrowedPointer::new(self[..].as_ptr(), self) }
101    }
102}
103
104impl<'a, T, const N: usize> BorrowForeignMut<'a> for [T; N]
105where
106    T: FixedAlloc + BorrowForeignMut<'a, Foreign = T, Storage = &'a mut T> + 'a,
107{
108    type Storage = &'a mut [T; N];
109
110    fn borrow_foreign_mut(&'a mut self) -> BorrowedMutPointer<Self, &'a mut Self> {
111        // SAFETY: data behind a shared reference cannot move
112        // as long as the reference is alive
113        unsafe { BorrowedMutPointer::new(self[..].as_mut_ptr(), self) }
114    }
115}
116
117unsafe impl<T, const N: usize> FixedAlloc for [T; N]
118where
119    T: FixedAlloc,
120{
121    unsafe fn clone_into_foreign(dest: *mut Self::Foreign, src: &Self) {
122        T::clone_from_native_slice(dest, &src[..]);
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use std::ffi::c_void;
129    use std::ptr;
130
131    use crate::foreign::*;
132
133    #[test]
134    fn test_slice_convert() {
135        let a = [123i8, 45i8, 67i8];
136        let i = &a[0..=1];
137        let p = i.clone_to_foreign();
138        unsafe {
139            assert_eq!(
140                libc::memcmp(
141                    i.as_ptr().cast::<c_void>(),
142                    p.as_ptr().cast::<c_void>(),
143                    i.len()
144                ),
145                0
146            );
147            assert_eq!(i, <[i8; 2]>::cloned_from_foreign(p.as_ptr()));
148        }
149
150        let p = i.clone_to_foreign();
151        unsafe {
152            assert_eq!(i, <[i8; 2]>::from_foreign(p.into_inner()));
153        }
154    }
155
156    #[test]
157    fn test_slice_borrow() {
158        let i = [123i8, 45i8];
159        let borrowed = i.borrow_foreign();
160        unsafe {
161            assert_eq!(
162                libc::memcmp(
163                    i.as_ptr().cast::<c_void>(),
164                    borrowed.as_ptr().cast::<c_void>(),
165                    i.len()
166                ),
167                0
168            );
169
170            let cloned = <[i8; 2]>::cloned_from_foreign(borrowed.as_ptr());
171            assert_eq!(i, cloned);
172        }
173    }
174
175    #[test]
176    fn test_slice_borrow_mut() {
177        let mut i = [123u8, 45u8];
178        let (p, len) = (i.as_ptr(), i.len());
179        let mut borrowed = i.borrow_foreign_mut();
180        unsafe {
181            assert_eq!(
182                libc::memcmp(p.cast::<c_void>(), borrowed.as_ptr().cast::<c_void>(), len),
183                0
184            );
185
186            ptr::write(borrowed.as_mut_ptr().offset(1), 234);
187            let cloned = <[u8; 2]>::cloned_from_foreign(borrowed.as_ptr());
188
189            assert_eq!(i[1], 234);
190            assert_eq!(i, cloned);
191        }
192    }
193
194    #[test]
195    fn test_array_convert() {
196        let i = [123i8, 45i8];
197        let p = i.clone_to_foreign();
198        unsafe {
199            assert_eq!(
200                libc::memcmp(
201                    i.as_ptr().cast::<c_void>(),
202                    p.as_ptr().cast::<c_void>(),
203                    i.len()
204                ),
205                0
206            );
207            assert_eq!(i, <[i8; 2]>::cloned_from_foreign(p.as_ptr()));
208        }
209
210        let p = i.clone_to_foreign();
211        unsafe {
212            assert_eq!(i, <[i8; 2]>::from_foreign(p.into_inner()));
213        }
214    }
215}