com/
abi_transferable.rs

1/// Types that are safe to transfer over a COM API boundary.
2///
3/// # Safety
4/// Implementing types only have associated `Abi` types that are
5/// safe to transfer over a COM FFI boundary. Implementing types
6/// must also be exactly equivalent to their associated types
7/// in layout and abi such that it is safe to transmute between the
8/// two types.
9pub unsafe trait AbiTransferable: Sized {
10    /// The FFI compatible type the implementing type can turn into.
11    type Abi;
12
13    /// Turn the type into the FFI ABI type.
14    fn get_abi(&self) -> Self::Abi;
15    /// Set the abi of the implementing type
16    fn set_abi(&mut self) -> *mut Self::Abi;
17
18    /// Convert into a reference to Self from a reference to the ABI
19    fn from_abi(abi: Self::Abi) -> Self {
20        // This must be safe for the implementing type to
21        // correctly implement this trait.
22        unsafe { core::mem::transmute_copy(&abi) }
23    }
24
25    /// Convert a pointer to a `Self::Abi` and and a length to a slice.
26    ///
27    /// # Safety
28    /// The `abi` pointer must be a valid pointer to an array of `Self::Abi` items of
29    /// `len` size for the lifetime `'a`. Nothing can mutate that array while
30    /// the slice exists.
31    unsafe fn slice_from_abi<'a>(abi: *const Self::Abi, len: usize) -> &'a [Self] {
32        core::slice::from_raw_parts(core::mem::transmute_copy(&abi), len)
33    }
34
35    /// Convert a pointer to a `Self::Abi` and and a length to a mutable slice.
36    ///
37    /// # Safety
38    /// The same rules apply as with `slice_from_abi` but no other references into
39    /// the slice are allowed while the slice exists.
40    unsafe fn slice_from_mut_abi<'a>(abi: *mut Self::Abi, len: usize) -> &'a mut [Self] {
41        core::slice::from_raw_parts_mut(core::mem::transmute_copy(&abi), len)
42    }
43
44    /// Converts and consumes the ABI transferable type into its ABI representation.
45    fn into_abi(self) -> Self::Abi {
46        // This must be safe for the implementing type to
47        // correctly implement this trait.
48        let abi = unsafe { core::mem::transmute_copy(&self) };
49        core::mem::forget(self);
50        abi
51    }
52}
53
54macro_rules! primitive_transferable_type {
55    ($($t:ty),+) => {
56        $(unsafe impl AbiTransferable for $t {
57            type Abi = Self;
58            fn get_abi(&self) -> Self::Abi {
59                *self
60            }
61            fn set_abi(&mut self) -> *mut Self::Abi {
62                self as *mut Self::Abi
63            }
64        })*
65    };
66}
67
68primitive_transferable_type! {
69    bool,
70    i8,
71    u8,
72    i16,
73    u16,
74    i32,
75    u32,
76    i64,
77    u64,
78    f32,
79    f64,
80    usize,
81    crate::sys::GUID
82}
83
84unsafe impl<T> AbiTransferable for *mut T {
85    type Abi = Self;
86    fn get_abi(&self) -> Self::Abi {
87        *self
88    }
89    fn set_abi(&mut self) -> *mut Self::Abi {
90        self as *mut Self::Abi
91    }
92}
93
94unsafe impl<T> AbiTransferable for *const T {
95    type Abi = Self;
96    fn get_abi(&self) -> Self::Abi {
97        *self
98    }
99    fn set_abi(&mut self) -> *mut Self::Abi {
100        self as *mut Self::Abi
101    }
102}
103
104unsafe impl<T: crate::Interface> AbiTransferable for T {
105    type Abi = core::ptr::NonNull<core::ptr::NonNull<<T as crate::Interface>::VTable>>;
106    fn get_abi(&self) -> Self::Abi {
107        self.as_raw()
108    }
109
110    fn set_abi(&mut self) -> *mut Self::Abi {
111        &mut self.as_raw()
112    }
113}
114
115unsafe impl<T: crate::Interface> AbiTransferable for Option<T> {
116    type Abi = *mut core::ptr::NonNull<<T as crate::Interface>::VTable>;
117    fn get_abi(&self) -> Self::Abi {
118        self.as_ref()
119            .map(|p| p.as_raw().as_ptr())
120            .unwrap_or(::core::ptr::null_mut())
121    }
122
123    fn set_abi(&mut self) -> *mut Self::Abi {
124        &mut self
125            .as_mut()
126            .map(|p| p.as_raw().as_ptr())
127            .unwrap_or(::core::ptr::null_mut())
128    }
129}