1use std::ops::Deref;
2use std::ptr::addr_of;
3use std::sync::Arc;
4
5use super::{ComPtr, ComRef, Guid, Interface};
6
7macro_rules! offset_of {
8 ($struct:ty, $field:tt) => {{
9 use ::std::ffi::c_void;
10 use ::std::mem::MaybeUninit;
11 use ::std::ptr::addr_of;
12
13 let dummy = MaybeUninit::<$struct>::uninit();
14 let base = dummy.as_ptr();
15 let field = addr_of!((*base).$field);
16
17 (field as *const c_void).offset_from(base as *const c_void)
18 }};
19}
20
21pub trait Wrapper<C: Class + ?Sized> {
30 unsafe fn data_from_header(ptr: *mut Header<C>) -> *mut C;
32
33 unsafe fn header_from_data(ptr: *mut C) -> *mut Header<C>;
35
36 unsafe fn add_ref(ptr: *mut C) -> usize;
38
39 unsafe fn release(ptr: *mut C) -> usize;
41}
42
43pub unsafe trait Construct<C: Class, W: Wrapper<C>, const OFFSET: isize>: Interface {
58 const OBJ: Self;
60}
61
62pub unsafe trait InterfaceList {
76 type Header;
78
79 fn query(iid: &Guid) -> Option<isize>;
83}
84
85pub unsafe trait MakeHeader<C, W>: InterfaceList
96where
97 C: Class,
98 W: Wrapper<C>,
99{
100 const HEADER: Self::Header;
101}
102
103pub trait Class {
107 type Interfaces: InterfaceList;
119}
120
121pub type Header<C> = <<C as Class>::Interfaces as InterfaceList>::Header;
123
124macro_rules! interface_list {
125 ($header:ident, $($interface:ident $index:tt),*) => {
126 #[repr(C)]
127 pub struct $header<$($interface),*>($($interface),*);
128
129 unsafe impl<$($interface: Interface),*> InterfaceList for ($($interface,)*) {
130 type Header = $header<$($interface),*>;
131
132 fn query(iid: &Guid) -> Option<isize> {
133 $(
134 if $interface::inherits(iid) {
135 return Some($index * std::mem::size_of::<*mut ()>() as isize);
136 }
137 )*
138
139 None
140 }
141 }
142
143 unsafe impl<C, W $(, $interface)*> MakeHeader<C, W> for ($($interface,)*)
144 where
145 C: Class,
146 W: Wrapper<C>,
147 $($interface: Construct<C, W, { $index * std::mem::size_of::<*mut ()>() as isize }>,)*
148 {
149 const HEADER: Self::Header = $header($($interface::OBJ),*);
150 }
151 }
152}
153
154interface_list!(Header1, I0 0);
155interface_list!(Header2, I0 0, I1 1);
156interface_list!(Header3, I0 0, I1 1, I2 2);
157interface_list!(Header4, I0 0, I1 1, I2 2, I3 3);
158interface_list!(Header5, I0 0, I1 1, I2 2, I3 3, I4 4);
159interface_list!(Header6, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5);
160interface_list!(Header7, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6);
161interface_list!(Header8, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7);
162interface_list!(Header9, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7, I8 8);
163interface_list!(Header10, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7, I8 8, I9 9);
164interface_list!(Header11, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7, I8 8, I9 9, I10 10);
165interface_list!(Header12, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7, I8 8, I9 9, I10 10, I11 11);
166interface_list!(Header13, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7, I8 8, I9 9, I10 10, I11 11, I12 12);
167interface_list!(Header14, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7, I8 8, I9 9, I10 10, I11 11, I12 12, I13 13);
168interface_list!(Header15, I0 0, I1 1, I2 2, I3 3, I4 4, I5 5, I6 6, I7 7, I8 8, I9 9, I10 10, I11 11, I12 12, I13 13, I14 14);
169
170#[repr(C)]
171struct ComWrapperInner<C: Class> {
172 header: Header<C>,
173 data: C,
174}
175
176pub struct ComWrapper<C: Class> {
181 inner: Arc<ComWrapperInner<C>>,
182}
183
184impl<C: Class> Clone for ComWrapper<C> {
185 fn clone(&self) -> ComWrapper<C> {
186 ComWrapper {
187 inner: self.inner.clone(),
188 }
189 }
190}
191
192unsafe impl<C: Class> Send for ComWrapper<C> where C: Send + Sync {}
193unsafe impl<C: Class> Sync for ComWrapper<C> where C: Send + Sync {}
194
195impl<C: Class> Deref for ComWrapper<C> {
196 type Target = C;
197
198 #[inline]
199 fn deref(&self) -> &Self::Target {
200 &self.inner.data
201 }
202}
203
204impl<C: Class> Wrapper<C> for ComWrapper<C> {
205 #[inline]
206 unsafe fn data_from_header(ptr: *mut Header<C>) -> *mut C {
207 (ptr as *mut u8)
208 .offset(-offset_of!(ComWrapperInner<C>, header))
209 .offset(offset_of!(ComWrapperInner<C>, data)) as *mut C
210 }
211
212 #[inline]
213 unsafe fn header_from_data(ptr: *mut C) -> *mut Header<C> {
214 (ptr as *mut u8)
215 .offset(-offset_of!(ComWrapperInner<C>, data))
216 .offset(offset_of!(ComWrapperInner<C>, header)) as *mut Header<C>
217 }
218
219 #[inline]
220 unsafe fn add_ref(ptr: *mut C) -> usize {
221 let wrapper_ptr = (ptr as *mut u8).offset(-offset_of!(ComWrapperInner<C>, data))
222 as *mut ComWrapperInner<C>;
223
224 let arc = Arc::from_raw(wrapper_ptr);
225 let result = Arc::strong_count(&arc) + 1;
226 let _ = Arc::into_raw(arc);
227
228 Arc::increment_strong_count(wrapper_ptr);
229
230 result
231 }
232
233 #[inline]
234 unsafe fn release(ptr: *mut C) -> usize {
235 let wrapper_ptr = (ptr as *mut u8).offset(-offset_of!(ComWrapperInner<C>, data))
236 as *mut ComWrapperInner<C>;
237
238 let arc = Arc::from_raw(wrapper_ptr);
239 let result = Arc::strong_count(&arc) - 1;
240 let _ = Arc::into_raw(arc);
241
242 Arc::decrement_strong_count(wrapper_ptr);
243
244 result
245 }
246}
247
248impl<C: Class> ComWrapper<C> {
249 #[inline]
251 pub fn new(data: C) -> ComWrapper<C>
252 where
253 C: 'static,
254 C::Interfaces: MakeHeader<C, Self>,
255 {
256 ComWrapper {
257 inner: Arc::new(ComWrapperInner {
258 header: C::Interfaces::HEADER,
259 data,
260 }),
261 }
262 }
263
264 #[inline]
268 pub fn as_com_ref<'a, I: Interface>(&'a self) -> Option<ComRef<'a, I>> {
269 if let Some(offset) = C::Interfaces::query(&I::IID) {
270 unsafe {
271 let wrapper_ptr = Arc::as_ptr(&self.inner) as *mut ComWrapperInner<C>;
272 let interface_ptr = (wrapper_ptr as *mut u8)
273 .offset(offset_of!(ComWrapperInner<C>, header))
274 .offset(offset) as *mut I;
275 Some(ComRef::from_raw_unchecked(interface_ptr))
276 }
277 } else {
278 None
279 }
280 }
281
282 #[inline]
286 pub fn to_com_ptr<I: Interface>(&self) -> Option<ComPtr<I>> {
287 if let Some(offset) = C::Interfaces::query(&I::IID) {
288 unsafe {
289 let wrapper_ptr = Arc::into_raw(self.inner.clone()) as *mut ComWrapperInner<C>;
290 let interface_ptr = (wrapper_ptr as *mut u8)
291 .offset(offset_of!(ComWrapperInner<C>, header))
292 .offset(offset) as *mut I;
293 Some(ComPtr::from_raw_unchecked(interface_ptr))
294 }
295 } else {
296 None
297 }
298 }
299}