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
125
126
127
128
129
130
131
132
133
134
135
/// Types that are safe to transfer over a COM API boundary.

///

/// # Safety

/// Implementing types only have associated `Abi` types that are

/// safe to transfer over a COM FFI boundary. Implementing types

/// must also be exactly equivalent to their associated types

/// in layout and abi such that it is safe to transmute between the

/// two types.

pub unsafe trait AbiTransferable: Sized {
    /// The FFI compatible type the implementing type can turn into.

    type Abi;

    /// Turn the type into the FFI ABI type.

    fn get_abi(&self) -> Self::Abi;
    /// Set the abi of the implementing type

    fn set_abi(&mut self) -> *mut Self::Abi;

    /// Convert into a reference to Self from a reference to the ABI

    fn from_abi(abi: &Self::Abi) -> &Self {
        // This must be safe for the implementing type to

        // correctly implement this trait.

        unsafe { std::mem::transmute_copy(&abi) }
    }

    /// The mut verison of `from_abi`

    fn from_mut_abi(abi: &mut Self::Abi) -> &mut Self {
        // This must be safe for the implementing type to

        // correctly implement this trait

        unsafe { std::mem::transmute_copy(&abi) }
    }

    /// Convert a pointer to a `Self::Abi` and and a length to a slice.

    ///

    /// # Safety

    /// The `abi` pointer must be a valid pointer to an array of `Self::Abi` items of

    /// `len` size for the lifetime `'a`. Nothing can mutate that array while

    /// the slice exists.

    unsafe fn slice_from_abi<'a>(abi: *const Self::Abi, len: usize) -> &'a [Self] {
        std::slice::from_raw_parts(std::mem::transmute_copy(&abi), len)
    }

    /// Convert a pointer to a `Self::Abi` and and a length to a mutable slice.

    ///

    /// # Safety

    /// The same rules apply as with `slice_from_abi` but no other references into

    /// the slice are allowed while the slice exists.

    unsafe fn slice_from_mut_abi<'a>(abi: *mut Self::Abi, len: usize) -> &'a mut [Self] {
        std::slice::from_raw_parts_mut(std::mem::transmute_copy(&abi), len)
    }

    /// Converts and consumes the ABI transferable type into its ABI representation.

    fn into_abi(self) -> Self::Abi {
        // This must be safe for the implementing type to

        // correctly implement this trait.

        let abi = unsafe { std::mem::transmute_copy(&self) };
        std::mem::forget(self);
        abi
    }
}

macro_rules! primitive_transferable_type {
    ($($t:ty),+) => {
        $(unsafe impl AbiTransferable for $t {
            type Abi = Self;
            fn get_abi(&self) -> Self::Abi {
                *self
            }
            fn set_abi(&mut self) -> *mut Self::Abi {
                self as *mut Self::Abi
            }
        })*
    };
}

primitive_transferable_type! {
    bool,
    i8,
    u8,
    i16,
    u16,
    i32,
    u32,
    i64,
    u64,
    f32,
    f64,
    crate::sys::GUID
}

unsafe impl<T> AbiTransferable for *mut T {
    type Abi = Self;
    fn get_abi(&self) -> Self::Abi {
        *self
    }
    fn set_abi(&mut self) -> *mut Self::Abi {
        self as *mut Self::Abi
    }
}

unsafe impl<T> AbiTransferable for *const T {
    type Abi = Self;
    fn get_abi(&self) -> Self::Abi {
        *self
    }
    fn set_abi(&mut self) -> *mut Self::Abi {
        self as *mut Self::Abi
    }
}

unsafe impl<T: crate::Interface> AbiTransferable for T {
    type Abi = std::ptr::NonNull<std::ptr::NonNull<<T as crate::Interface>::VTable>>;
    fn get_abi(&self) -> Self::Abi {
        self.as_raw()
    }

    fn set_abi(&mut self) -> *mut Self::Abi {
        &mut self.as_raw()
    }
}

unsafe impl<T: crate::Interface> AbiTransferable for Option<T> {
    type Abi = *mut std::ptr::NonNull<<T as crate::Interface>::VTable>;
    fn get_abi(&self) -> Self::Abi {
        self.as_ref()
            .map(|p| p.as_raw().as_ptr())
            .unwrap_or(::std::ptr::null_mut())
    }

    fn set_abi(&mut self) -> *mut Self::Abi {
        &mut self
            .as_mut()
            .map(|p| p.as_raw().as_ptr())
            .unwrap_or(::std::ptr::null_mut())
    }
}