hs_bindgen_traits/vec.rs
1use crate::{private, FromReprC, FromReprRust};
2
3// FIXME: study what could be a good `Vec<T>`/`&[T]` traits ergonomics ...
4// n.b. the concept of `slice` have no C equivalent ...
5// https://users.rust-lang.org/t/55118
6
7impl<T, const N: usize> FromReprRust<*const T> for &[T; N]
8where
9 *const T: private::CFFISafe,
10{
11 #[inline]
12 #[allow(clippy::not_unsafe_ptr_arg_deref)]
13 fn from(ptr: *const T) -> Self {
14 let s = unsafe { std::slice::from_raw_parts(ptr, N) };
15 s.try_into().unwrap_or_else(|_| {
16 let ty = std::any::type_name::<T>();
17 panic!("impossible to convert &[{ty}] into &[{ty}; {N}]");
18 })
19 }
20}
21
22impl<T> FromReprC<Vec<T>> for *const T
23where
24 *const T: private::CFFISafe,
25{
26 #[inline]
27 fn from(v: Vec<T>) -> Self {
28 let x: *const T = v.as_ptr();
29 // since the value is passed to Haskell runtime we want Rust to never
30 // drop it!
31 std::mem::forget(v);
32 // FIXME: I should double-check that this does not leak memory and
33 // that the value is well handled by GHC tracing Garbage Collector
34 x
35 // if not, we should export a utility function to let user drop
36 // the value, this technique was suggested e.g. here:
37 // https://stackoverflow.com/questions/39224904
38 }
39}
40
41#[test]
42fn _1() {
43 let x = &[1, 2, 3]; // FIXME: use Arbitrary crate
44 let y: &[i32; 3] = FromReprRust::from(FromReprC::from(x.to_vec()));
45 assert!(x == y);
46}