1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Representations of C types for the high layer.

use std::marker::PhantomData;

use super::super::middle;

/// Represents a C type statically associated with a Rust type.
///
/// In particular, the run-time value describes a particular C type,
/// while the type parameter `T` is the equivalent Rust type.
/// Instances of this type are created via the
/// [`CType`](trait.CType.html) trait.
#[derive(Clone, Debug)]
pub struct Type<T> {
    untyped: middle::Type,
    _marker: PhantomData<*mut T>,
}

impl<T> Type<T> {
    fn make(untyped: middle::Type) -> Self {
        Type {
            untyped,
            _marker: PhantomData,
        }
    }

    /// Gets the underlying representation as used by the
    /// [`middle`](../../middle/index.html) layer.
    pub fn into_middle(self) -> middle::Type {
        self.untyped
    }
}

/// Types that we can automatically marshall to/from C.
///
/// In particular, for any type `T` that implements `CType`, we can
/// get a `Type<T>` for describing that type.
/// This trait is unsafe to implement because if the libffi type
/// associated with a Rust type doesn’t match then we get
/// undefined behavior.
pub unsafe trait CType : Copy {
    /// Creates or retrieves a `Type<T>` for any type `T: CType`.
    ///
    /// We can use the resulting object to assemble a CIF to set up
    /// a call that uses type `T`.
    fn reify() -> Type<Self>;
}

macro_rules! impl_ffi_type {
    ($type_:ty, $cons:ident) => {
        unsafe impl<> CType for $type_ {
            fn reify() -> Type<Self> {
                Type::make(middle::Type::$cons())
            }
        }
    };
    ($type_:ident) => {
        impl_ffi_type!($type_, $type_);
    };
}

impl_ffi_type!(u8);
impl_ffi_type!(i8);
impl_ffi_type!(u16);
impl_ffi_type!(i16);
impl_ffi_type!(u32);
impl_ffi_type!(i32);
impl_ffi_type!(u64);
impl_ffi_type!(i64);
impl_ffi_type!(f32);
impl_ffi_type!(f64);
impl_ffi_type!(usize);
impl_ffi_type!(isize);
impl_ffi_type!((), void);

// Why is the complex stuff even here? It doesn’t work yet because
// libffi doesn’t support it, so it should probably go away and come
// back when it’s actually useful. Also, the definitions for c_c32 and
// c_c64 should come from elsewhere (the num package?), but that
// elsewhere doesn’t seem to exist yet.

/// Laid out the same as C11 `float complex` and C++11
/// `std::complex<float>`.
///
/// This item is enabled by `#[cfg(feature = "complex")]`.
///
/// # Warning
///
/// This type does not obey the ABI, and as such should not be passed by
/// value to or from a C or C++ function. Passing it via a pointer is
/// okay. Theoretically, passing it via libffi is okay, but libffi
/// doesn’t have complex support on most platforms yet.
#[allow(non_camel_case_types)]
#[cfg(feature = "complex")]
pub type c_c32 = [f32; 2];

/// Laid out the same as C11 `double complex` and C++11
/// `std::complex<double>`.
///
/// This item is enabled by `#[cfg(feature = "complex")]`.
///
/// # Warning
///
/// This type does not obey the ABI, and as such should not be passed by
/// value to or from a C or C++ function. Passing it via a pointer is
/// okay. Theoretically, passing it via libffi is okay, but libffi
/// doesn’t have complex support on most platforms yet.
#[allow(non_camel_case_types)]
#[cfg(feature = "complex")]
pub type c_c64 = [f64; 2];

#[cfg(feature = "complex")]
impl_ffi_type!(c_c32, c32);

#[cfg(feature = "complex")]
impl_ffi_type!(c_c64, c64);

unsafe impl<T> CType for *const T {
    fn reify() -> Type<Self> { Type::make(middle::Type::pointer()) }
}

unsafe impl<T> CType for *mut T {
    fn reify() -> Type<Self> { Type::make(middle::Type::pointer()) }
}