use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr; use winapi::ctypes::c_void; use winapi::um::unknwnbase::IUnknown; use winapi::Interface; use D3DResult; #[repr(transparent)] pub struct WeakPtr(*mut T); impl WeakPtr { pub fn null() -> Self { WeakPtr(ptr::null_mut()) } pub unsafe fn from_raw(raw: *mut T) -> Self { WeakPtr(raw) } pub fn is_null(&self) -> bool { self.0.is_null() } pub fn as_ptr(&self) -> *const T { self.0 } pub fn as_mut_ptr(&self) -> *mut T { self.0 } pub unsafe fn mut_void(&mut self) -> *mut *mut c_void { &mut self.0 as *mut *mut _ as *mut *mut _ } } impl WeakPtr { pub unsafe fn as_unknown(&self) -> &IUnknown { debug_assert!(!self.is_null()); &*(self.0 as *mut IUnknown) } // Cast creates a new WeakPtr requiring explicit destroy call. pub unsafe fn cast(&self) -> D3DResult> where U: Interface, { let mut obj = WeakPtr::::null(); let hr = self .as_unknown() .QueryInterface(&U::uuidof(), obj.mut_void()); (obj, hr) } // Destroying one instance of the WeakPtr will invalidate all // copies and clones. pub unsafe fn destroy(&self) { self.as_unknown().Release(); } } impl Clone for WeakPtr { fn clone(&self) -> Self { WeakPtr(self.0) } } impl Copy for WeakPtr {} impl Deref for WeakPtr { type Target = T; fn deref(&self) -> &T { debug_assert!(!self.is_null()); unsafe { &*self.0 } } } impl fmt::Debug for WeakPtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "WeakPtr( ptr: {:?} )", self.0) } } impl PartialEq<*mut T> for WeakPtr { fn eq(&self, other: &*mut T) -> bool { self.0 == *other } } impl PartialEq for WeakPtr { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } impl Hash for WeakPtr { fn hash(&self, state: &mut H) { self.0.hash(state); } }