deno_libffi/high/
types.rs

1//! Representations of C types for the high layer.
2
3use std::marker::PhantomData;
4
5use super::super::middle;
6
7/// Represents a C type statically associated with a Rust type.
8///
9/// In particular, the run-time value describes a particular C type,
10/// while the type parameter `T` is the equivalent Rust type.
11/// Instances of this type are created via the
12/// [`CType`](trait.CType.html) trait.
13#[derive(Clone, Debug)]
14pub struct Type<T> {
15    untyped: middle::Type,
16    _marker: PhantomData<*mut T>,
17}
18
19impl<T> Type<T> {
20    fn make(untyped: middle::Type) -> Self {
21        Type {
22            untyped,
23            _marker: PhantomData,
24        }
25    }
26
27    /// Gets the underlying representation as used by the
28    /// [`middle`](../../middle/index.html) layer.
29    pub fn into_middle(self) -> middle::Type {
30        self.untyped
31    }
32}
33
34/// Types that we can automatically marshall to/from C.
35///
36/// In particular, for any type `T` that implements `CType`, we can
37/// get a `Type<T>` for describing that type.
38/// This trait is unsafe to implement because if the libffi type
39/// associated with a Rust type doesn’t match then we get
40/// undefined behavior.
41pub unsafe trait CType: Copy {
42    /// Creates or retrieves a `Type<T>` for any type `T: CType`.
43    ///
44    /// We can use the resulting object to assemble a CIF to set up
45    /// a call that uses type `T`.
46    fn reify() -> Type<Self>;
47}
48
49macro_rules! impl_ffi_type {
50    ($type_:ty, $cons:ident) => {
51        unsafe impl CType for $type_ {
52            fn reify() -> Type<Self> {
53                Type::make(middle::Type::$cons())
54            }
55        }
56    };
57    ($type_:ident) => {
58        impl_ffi_type!($type_, $type_);
59    };
60}
61
62impl_ffi_type!(u8);
63impl_ffi_type!(i8);
64impl_ffi_type!(u16);
65impl_ffi_type!(i16);
66impl_ffi_type!(u32);
67impl_ffi_type!(i32);
68impl_ffi_type!(u64);
69impl_ffi_type!(i64);
70impl_ffi_type!(f32);
71impl_ffi_type!(f64);
72impl_ffi_type!(usize);
73impl_ffi_type!(isize);
74impl_ffi_type!((), void);
75
76// Why is the complex stuff even here? It doesn’t work yet because
77// libffi doesn’t support it, so it should probably go away and come
78// back when it’s actually useful. Also, the definitions for c_c32 and
79// c_c64 should come from elsewhere (the num package?), but that
80// elsewhere doesn’t seem to exist yet.
81
82/// Laid out the same as C11 `float complex` and C++11
83/// `std::complex<float>`.
84///
85/// This item is enabled by `#[cfg(feature = "complex")]`.
86///
87/// # Warning
88///
89/// This type does not obey the ABI, and as such should not be passed by
90/// value to or from a C or C++ function. Passing it via a pointer is
91/// okay. Theoretically, passing it via libffi is okay, but libffi
92/// doesn’t have complex support on most platforms yet.
93#[allow(non_camel_case_types)]
94#[cfg(feature = "complex")]
95pub type c_c32 = [f32; 2];
96
97/// Laid out the same as C11 `double complex` and C++11
98/// `std::complex<double>`.
99///
100/// This item is enabled by `#[cfg(feature = "complex")]`.
101///
102/// # Warning
103///
104/// This type does not obey the ABI, and as such should not be passed by
105/// value to or from a C or C++ function. Passing it via a pointer is
106/// okay. Theoretically, passing it via libffi is okay, but libffi
107/// doesn’t have complex support on most platforms yet.
108#[allow(non_camel_case_types)]
109#[cfg(feature = "complex")]
110pub type c_c64 = [f64; 2];
111
112#[cfg(feature = "complex")]
113impl_ffi_type!(c_c32, c32);
114
115#[cfg(feature = "complex")]
116impl_ffi_type!(c_c64, c64);
117
118unsafe impl<T> CType for *const T {
119    fn reify() -> Type<Self> {
120        Type::make(middle::Type::pointer())
121    }
122}
123
124unsafe impl<T> CType for *mut T {
125    fn reify() -> Type<Self> {
126        Type::make(middle::Type::pointer())
127    }
128}