ferroui_microcom/
com_ptr.rs1use std::ffi::c_void;
2use std::fmt;
3use std::marker::PhantomData;
4use std::ops::Deref;
5use std::ptr::NonNull;
6
7use crate::{HResult, Interface, E_NOINTERFACE, S_OK};
8
9#[repr(transparent)]
13pub struct ComPtr<T: Interface> {
14 ptr: NonNull<T>,
15 _marker: PhantomData<*mut T>,
16}
17
18impl<T: Interface> ComPtr<T> {
19 #[inline]
26 pub unsafe fn from_raw(raw: *mut T) -> Option<Self> {
27 NonNull::new(raw).map(|ptr| ComPtr { ptr, _marker: PhantomData })
28 }
29
30 #[inline]
35 pub unsafe fn from_raw_add_ref(raw: *mut T) -> Option<Self> {
36 let p = Self::from_raw(raw)?;
37 p.as_unknown().add_ref();
38 Some(p)
39 }
40
41 #[inline]
43 pub fn from_ref(r: &T) -> Self {
44 unsafe { Self::from_raw_add_ref(r.as_raw()).unwrap_unchecked() }
46 }
47
48 #[inline]
50 pub fn as_ptr(&self) -> *mut T {
51 self.ptr.as_ptr()
52 }
53
54 #[inline]
56 pub fn into_raw(self) -> *mut T {
57 let p = self.ptr.as_ptr();
58 std::mem::forget(self);
59 p
60 }
61
62 pub fn cast<U: Interface>(&self) -> Result<ComPtr<U>, HResult> {
69 let mut last = E_NOINTERFACE;
70 for iid in [U::IID.as_com_h_materialized(), U::IID] {
71 let mut out: *mut c_void = std::ptr::null_mut();
72 let hr = unsafe { self.as_unknown().query_interface_raw(&iid, &mut out) };
74 if hr == S_OK {
75 return unsafe { ComPtr::from_raw(out as *mut U) }.ok_or(HResult::POINTER);
77 }
78 last = hr;
79 }
80 Err(HResult(last))
81 }
82}
83
84impl<T: Interface> Deref for ComPtr<T> {
85 type Target = T;
86 #[inline]
87 fn deref(&self) -> &T {
88 unsafe { self.ptr.as_ref() }
90 }
91}
92
93impl<T: Interface> Clone for ComPtr<T> {
94 #[inline]
95 fn clone(&self) -> Self {
96 unsafe { self.as_unknown().add_ref() };
98 ComPtr { ptr: self.ptr, _marker: PhantomData }
99 }
100}
101
102impl<T: Interface> Drop for ComPtr<T> {
103 #[inline]
104 fn drop(&mut self) {
105 unsafe { self.as_unknown().release() };
107 }
108}
109
110impl<T: Interface> PartialEq for ComPtr<T> {
111 fn eq(&self, other: &Self) -> bool {
112 self.ptr == other.ptr
113 }
114}
115
116impl<T: Interface> fmt::Debug for ComPtr<T> {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "ComPtr<{}>({:p})", T::NAME, self.ptr.as_ptr())
119 }
120}