1use super::*;
2
3/// A WinRT object that may be used as a polymorphic stand-in for any WinRT class, interface, or boxed value.
4/// [`IInspectable`] represents the
5/// [IInspectable](https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nn-inspectable-iinspectable)
6/// interface.
7#[repr(transparent)]
8#[derive(Clone, PartialEq, Eq)]
9pub struct IInspectable(pub IUnknown);
10
11impl IInspectable {
12 /// Returns the canonical type name for the underlying object.
13 pub fn GetRuntimeClassName(&self) -> Result<HSTRING> {
14 unsafe {
15 let mut abi: *mut c_void = std::ptr::null_mut();
16 (self.vtable().GetRuntimeClassName)(std::mem::transmute_copy(self), &mut abi).ok()?;
17 Ok(std::mem::transmute(src:abi))
18 }
19 }
20}
21
22#[doc(hidden)]
23#[repr(C)]
24pub struct IInspectable_Vtbl {
25 pub base: IUnknown_Vtbl,
26 pub GetIids: unsafe extern "system" fn(this: *mut std::ffi::c_void, count: *mut u32, values: *mut *mut GUID) -> HRESULT,
27 pub GetRuntimeClassName: unsafe extern "system" fn(this: *mut std::ffi::c_void, value: *mut *mut std::ffi::c_void) -> HRESULT,
28 pub GetTrustLevel: unsafe extern "system" fn(this: *mut std::ffi::c_void, value: *mut i32) -> HRESULT,
29}
30
31unsafe impl Interface for IInspectable {
32 type Vtable = IInspectable_Vtbl;
33}
34
35unsafe impl ComInterface for IInspectable {
36 const IID: GUID = GUID::from_u128(uuid:0xaf86e2e0_b12d_4c6a_9c5a_d7aa65101e90);
37}
38
39impl CanInto<IUnknown> for IInspectable {}
40
41impl RuntimeType for IInspectable {
42 const SIGNATURE: crate::imp::ConstBuffer = crate::imp::ConstBuffer::from_slice(b"cinterface(IInspectable)");
43}
44
45impl RuntimeName for IInspectable {}
46
47#[cfg(feature = "implement")]
48impl IInspectable_Vtbl {
49 pub const fn new<Identity: IUnknownImpl, Name: RuntimeName, const OFFSET: isize>() -> Self {
50 unsafe extern "system" fn GetIids(_: *mut std::ffi::c_void, count: *mut u32, values: *mut *mut GUID) -> HRESULT {
51 // Note: even if we end up implementing this in future, it still doesn't need a this pointer
52 // since the data to be returned is type- not instance-specific so can be shared for all
53 // interfaces.
54 *count = 0;
55 *values = std::ptr::null_mut();
56 HRESULT(0)
57 }
58 unsafe extern "system" fn GetRuntimeClassName<T: RuntimeName>(_: *mut std::ffi::c_void, value: *mut *mut std::ffi::c_void) -> HRESULT {
59 let h: HSTRING = T::NAME.into(); // TODO: should be try_into
60 *value = std::mem::transmute(h);
61 HRESULT(0)
62 }
63 unsafe extern "system" fn GetTrustLevel(_: *mut std::ffi::c_void, value: *mut i32) -> HRESULT {
64 // Note: even if we end up implementing this in future, it still doesn't need a this pointer
65 // since the data to be returned is type- not instance-specific so can be shared for all
66 // interfaces.
67 *value = 0;
68 HRESULT(0)
69 }
70 Self { base: IUnknown_Vtbl::new::<Identity, OFFSET>(), GetIids, GetRuntimeClassName: GetRuntimeClassName::<Name>, GetTrustLevel }
71 }
72}
73
74impl std::fmt::Debug for IInspectable {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 // Attempts to retrieve the string representation of the object via the
77 // IStringable interface. If that fails, it will use the canonical type
78 // name to give some idea of what the object represents.
79 let name: HSTRING = <Self as ComInterface>::cast::<imp::IStringable>(self).and_then(|s| s.ToString()).or_else(|_| self.GetRuntimeClassName()).unwrap_or_default();
80 write!(f, "\"{}\"", name)
81 }
82}
83
84macro_rules! primitive_boxed_type {
85 ($(($t:ty, $m:ident)),+) => {
86 $(impl std::convert::TryFrom<$t> for IInspectable {
87 type Error = Error;
88 fn try_from(value: $t) -> Result<Self> {
89 imp::PropertyValue::$m(value)
90 }
91 }
92 impl std::convert::TryFrom<IInspectable> for $t {
93 type Error = Error;
94 fn try_from(value: IInspectable) -> Result<Self> {
95 <IInspectable as ComInterface>::cast::<imp::IReference<$t>>(&value)?.Value()
96 }
97 }
98 impl std::convert::TryFrom<&IInspectable> for $t {
99 type Error = Error;
100 fn try_from(value: &IInspectable) -> Result<Self> {
101 <IInspectable as ComInterface>::cast::<imp::IReference<$t>>(value)?.Value()
102 }
103 })*
104 };
105}
106primitive_boxed_type! {
107 (bool, CreateBoolean),
108 (u8, CreateUInt8),
109 (i16, CreateInt16),
110 (u16, CreateUInt16),
111 (i32, CreateInt32),
112 (u32, CreateUInt32),
113 (i64, CreateInt64),
114 (u64, CreateUInt64),
115 (f32, CreateSingle),
116 (f64, CreateDouble)
117}
118impl std::convert::TryFrom<&str> for IInspectable {
119 type Error = Error;
120 fn try_from(value: &str) -> Result<Self> {
121 let value: HSTRING = value.into();
122 imp::PropertyValue::CreateString(&value)
123 }
124}
125impl std::convert::TryFrom<HSTRING> for IInspectable {
126 type Error = Error;
127 fn try_from(value: HSTRING) -> Result<Self> {
128 imp::PropertyValue::CreateString(&value)
129 }
130}
131impl std::convert::TryFrom<&HSTRING> for IInspectable {
132 type Error = Error;
133 fn try_from(value: &HSTRING) -> Result<Self> {
134 imp::PropertyValue::CreateString(value)
135 }
136}
137impl std::convert::TryFrom<IInspectable> for HSTRING {
138 type Error = Error;
139 fn try_from(value: IInspectable) -> Result<Self> {
140 <IInspectable as ComInterface>::cast::<imp::IReference<HSTRING>>(&value)?.Value()
141 }
142}
143impl std::convert::TryFrom<&IInspectable> for HSTRING {
144 type Error = Error;
145 fn try_from(value: &IInspectable) -> Result<Self> {
146 <IInspectable as ComInterface>::cast::<imp::IReference<HSTRING>>(self:value)?.Value()
147 }
148}
149