1use crate::{
2 com_class, com_interface, type_system::TypeSystemName, ComBox, ComError, ComItf, ComRc,
3 ComResult, ExternOutput, ExternType, ForeignType, GUID,
4};
5
6use std::borrow::Cow;
7
8#[derive(Fail, Debug)]
9pub enum TypeLibError
10{
11 #[fail(display = "COM error occurred: {}", _0)]
12 ComError(ComError),
13}
14
15impl From<ComError> for TypeLibError
16{
17 fn from(s: ComError) -> Self
18 {
19 TypeLibError::ComError(s)
20 }
21}
22
23mod from_impls;
24
25#[derive(Debug)]
29pub struct InterfaceRef
30{
31 pub name: Cow<'static, str>,
32 pub iid_automation: GUID,
33 pub iid_raw: GUID,
34}
35
36#[com_class(IIntercomTypeLib)]
39#[derive(Debug)]
40pub struct TypeLib
41{
42 pub name: Cow<'static, str>,
43 pub libid: GUID,
44 pub version: Cow<'static, str>,
45 pub types: Vec<TypeInfo>,
46}
47
48#[com_interface]
49pub trait IIntercomTypeLib
50{
51 fn get_info(&self) -> ComResult<(String, GUID, String)>;
52 fn get_type_count(&self) -> ComResult<u32>;
53 fn get_type(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomTypeInfo>>;
54}
55
56#[derive(Debug)]
59pub enum TypeInfo
60{
61 Class(ComBox<CoClass>),
62 Interface(ComBox<Interface>),
63}
64
65#[derive(ExternType, ExternOutput, ForeignType, Debug)]
66#[repr(C)]
67pub enum TypeInfoKind
68{
69 CoClass,
70 Interface,
71}
72
73#[com_interface]
74pub trait IIntercomTypeInfo
75{
76 fn get_name(&self) -> ComResult<String>;
77 fn get_kind(&self) -> ComResult<TypeInfoKind>;
78}
79
80#[com_class(IIntercomTypeInfo, IIntercomCoClass)]
83#[derive(Debug)]
84pub struct CoClass
85{
86 pub name: Cow<'static, str>,
87 pub clsid: GUID,
88 pub interfaces: Vec<InterfaceRef>,
89}
90
91#[com_interface]
92pub trait IIntercomCoClass
93{
94 fn get_name(&self) -> ComResult<String>;
96
97 fn get_clsid(&self) -> ComResult<GUID>;
98 fn get_interface_count(&self) -> ComResult<u32>;
99 fn get_interface_ref(&self, idx: u32, ts: TypeSystemName) -> ComResult<(String, GUID)>;
100}
101
102#[com_class(IIntercomTypeInfo, IIntercomInterface)]
105#[derive(Debug)]
106pub struct Interface
107{
108 pub name: Cow<'static, str>,
109 pub variants: Vec<ComBox<InterfaceVariant>>,
110 pub options: InterfaceOptions,
111}
112
113#[derive(Debug, Clone, Default, ExternType, ExternOutput, ForeignType)]
114#[repr(C)]
115pub struct InterfaceOptions
116{
117 pub class_impl_interface: bool,
118 pub __non_exhaustive: (),
119}
120
121#[com_class(IIntercomInterfaceVariant)]
122#[derive(Debug)]
123pub struct InterfaceVariant
124{
125 pub ts: TypeSystemName,
126 pub iid: GUID,
127 pub methods: Vec<ComBox<Method>>,
128}
129
130#[com_interface]
131pub trait IIntercomInterface
132{
133 fn get_name(&self) -> ComResult<String>;
135 fn get_options(&self) -> ComResult<InterfaceOptions>;
136
137 fn get_variant_count(&self) -> ComResult<u32>;
138 fn get_variant(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomInterfaceVariant>>;
139}
140
141#[com_interface]
142pub trait IIntercomInterfaceVariant
143{
144 fn get_type_system(&self) -> ComResult<TypeSystemName>;
145 fn get_iid(&self) -> ComResult<GUID>;
146 fn get_method_count(&self) -> ComResult<u32>;
147 fn get_method(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomMethod>>;
148}
149
150#[com_class(IIntercomMethod)]
153#[derive(Debug)]
154pub struct Method
155{
156 pub name: Cow<'static, str>,
157 pub return_type: Arg,
158 pub parameters: Vec<Arg>,
159}
160
161#[derive(Debug)]
162pub struct Arg
163{
164 pub name: Cow<'static, str>,
165 pub ty: Cow<'static, str>,
166 pub indirection_level: u32,
167 pub direction: Direction,
168}
169
170#[derive(Debug, Clone, Copy, ExternType, ExternOutput, ForeignType, PartialEq, Eq)]
171#[repr(C)]
172pub enum Direction
173{
174 In,
175 Out,
176 Retval,
177 Return,
178}
179
180#[com_interface]
181pub trait IIntercomMethod
182{
183 fn get_name(&self) -> ComResult<String>;
184 fn get_return_type(&self) -> ComResult<(String, u32)>;
185 fn get_parameter_count(&self) -> ComResult<u32>;
186 fn get_parameter(&self, idx: u32) -> ComResult<(String, String, u32, Direction)>;
187}
188
189impl IIntercomTypeLib for TypeLib
192{
193 fn get_info(&self) -> ComResult<(String, GUID, String)>
194 {
195 Ok((
196 self.name.to_string(),
197 self.libid.clone(),
198 self.version.to_string(),
199 ))
200 }
201
202 fn get_type_count(&self) -> ComResult<u32>
203 {
204 Ok(self.types.len() as u32)
205 }
206
207 fn get_type(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomTypeInfo>>
208 {
209 Ok(match &self.types[idx as usize] {
210 TypeInfo::Class(cls) => ComRc::from(cls),
211 TypeInfo::Interface(itf) => ComRc::from(itf),
212 })
213 }
214}
215
216impl IIntercomTypeInfo for CoClass
217{
218 fn get_name(&self) -> ComResult<String>
219 {
220 Ok(self.name.to_string())
221 }
222
223 fn get_kind(&self) -> ComResult<TypeInfoKind>
224 {
225 Ok(TypeInfoKind::CoClass)
226 }
227}
228
229impl IIntercomCoClass for CoClass
230{
231 fn get_name(&self) -> ComResult<String>
232 {
233 Ok(self.name.to_string())
234 }
235
236 fn get_clsid(&self) -> ComResult<GUID>
237 {
238 Ok(self.clsid.clone())
239 }
240 fn get_interface_count(&self) -> ComResult<u32>
241 {
242 Ok(self.interfaces.len() as u32)
243 }
244
245 fn get_interface_ref(&self, idx: u32, ts: TypeSystemName) -> ComResult<(String, GUID)>
246 {
247 let itf = &self.interfaces[idx as usize];
248 Ok((
249 itf.name.to_string(),
250 match ts {
251 TypeSystemName::Automation => itf.iid_automation.clone(),
252 TypeSystemName::Raw => itf.iid_raw.clone(),
253 },
254 ))
255 }
256}
257
258impl IIntercomTypeInfo for Interface
259{
260 fn get_name(&self) -> ComResult<String>
261 {
262 Ok(self.name.to_string())
263 }
264
265 fn get_kind(&self) -> ComResult<TypeInfoKind>
266 {
267 Ok(TypeInfoKind::Interface)
268 }
269}
270
271impl IIntercomInterface for Interface
272{
273 fn get_name(&self) -> ComResult<String>
274 {
275 Ok(self.name.to_string())
276 }
277
278 fn get_options(&self) -> ComResult<InterfaceOptions>
279 {
280 Ok(self.options.clone())
281 }
282
283 fn get_variant_count(&self) -> ComResult<u32>
284 {
285 Ok(self.variants.len() as u32)
286 }
287
288 fn get_variant(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomInterfaceVariant>>
289 {
290 Ok(ComRc::from(&self.variants[idx as usize]))
291 }
292}
293
294impl IIntercomInterfaceVariant for InterfaceVariant
295{
296 fn get_type_system(&self) -> ComResult<TypeSystemName>
297 {
298 Ok(self.ts)
299 }
300
301 fn get_iid(&self) -> ComResult<GUID>
302 {
303 Ok(self.iid.clone())
304 }
305
306 fn get_method_count(&self) -> ComResult<u32>
307 {
308 Ok(self.methods.len() as u32)
309 }
310
311 fn get_method(&self, idx: u32) -> ComResult<ComRc<dyn IIntercomMethod>>
312 {
313 Ok(ComRc::from(&self.methods[idx as usize]))
314 }
315}
316
317impl IIntercomMethod for Method
318{
319 fn get_name(&self) -> ComResult<String>
320 {
321 Ok(self.name.to_string())
322 }
323
324 fn get_return_type(&self) -> ComResult<(String, u32)>
325 {
326 Ok((
327 self.return_type.ty.to_string(),
328 self.return_type.indirection_level,
329 ))
330 }
331
332 fn get_parameter_count(&self) -> ComResult<u32>
333 {
334 Ok(self.parameters.len() as u32)
335 }
336 fn get_parameter(&self, idx: u32) -> ComResult<(String, String, u32, Direction)>
337 {
338 let arg = &self.parameters[idx as usize];
339 Ok((
340 arg.name.to_string(),
341 arg.ty.to_string(),
342 arg.indirection_level,
343 arg.direction,
344 ))
345 }
346}
347
348impl CoClass
349{
350 pub fn __new(name: Cow<'static, str>, clsid: GUID, interfaces: Vec<InterfaceRef>) -> Self
351 {
352 Self {
353 name,
354 clsid,
355 interfaces,
356 }
357 }
358}
359
360impl TypeLib
361{
362 pub fn __new(
363 name: Cow<'static, str>,
364 libid: GUID,
365 version: Cow<'static, str>,
366 mut types: Vec<TypeInfo>,
367 ) -> TypeLib
368 {
369 types.sort_by_key(|item| match item {
370 TypeInfo::Class(cls) => ("class", cls.as_ref().name.to_string()),
371 TypeInfo::Interface(itf) => ("itf", itf.as_ref().name.to_string()),
372 });
373 types.dedup_by_key(|item| match item {
374 TypeInfo::Class(cls) => ("class", cls.as_ref().name.to_string()),
375 TypeInfo::Interface(itf) => ("itf", itf.as_ref().name.to_string()),
376 });
377 TypeLib {
378 name,
379 libid,
380 version,
381 types,
382 }
383 }
384}