use std::ffi::c_void;
use crate::{Guid, RawHResult};
pub unsafe trait Interface: Sized + 'static {
const IID: Guid;
const NAME: &'static str;
type Vtbl: 'static;
fn matches_iid(iid: &Guid) -> bool;
#[inline]
fn as_unknown(&self) -> &IUnknown {
unsafe { &*(self as *const Self as *const IUnknown) }
}
#[inline]
fn as_raw(&self) -> *mut Self {
self as *const Self as *mut Self
}
}
#[repr(C)]
pub struct IUnknownVtbl {
pub query_interface: unsafe extern "system" fn(
this: *mut c_void,
riid: *const Guid,
ppv: *mut *mut c_void,
) -> RawHResult,
pub add_ref: unsafe extern "system" fn(this: *mut c_void) -> u32,
pub release: unsafe extern "system" fn(this: *mut c_void) -> u32,
}
#[repr(C)]
pub struct IUnknown {
vtbl: *const IUnknownVtbl,
}
unsafe impl Interface for IUnknown {
const IID: Guid = Guid::from_u128(0x00000000_0000_0000_C000_000000000046);
const NAME: &'static str = "IUnknown";
type Vtbl = IUnknownVtbl;
fn matches_iid(iid: &Guid) -> bool {
*iid == Self::IID || *iid == Self::IID.as_com_h_materialized()
}
}
impl IUnknown {
#[inline]
pub unsafe fn query_interface_raw(&self, riid: &Guid, ppv: *mut *mut c_void) -> RawHResult {
((*self.vtbl).query_interface)(self as *const _ as *mut c_void, riid, ppv)
}
#[inline]
pub unsafe fn add_ref(&self) -> u32 {
((*self.vtbl).add_ref)(self as *const _ as *mut c_void)
}
#[inline]
pub unsafe fn release(&self) -> u32 {
((*self.vtbl).release)(self as *const _ as *mut c_void)
}
}
pub trait IUnknownImpl {}
impl<T: ?Sized> IUnknownImpl for T {}