Skip to main content

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}