1use super::*;
2
3#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
4pub enum InterfaceKind {
5 None,
6 Default,
7 Static,
8 Composable,
9 Base,
10}
11
12#[derive(Clone, Debug)]
13pub enum MethodOrName {
14 Method(Method),
15 Name(&'static str),
16}
17
18#[derive(Clone, Debug)]
19pub struct Interface {
20 pub def: TypeDef,
21 pub generics: Vec<Type>,
22 pub kind: InterfaceKind,
23}
24
25impl PartialEq for Interface {
26 fn eq(&self, other: &Self) -> bool {
27 self.def == other.def
28 }
29}
30
31impl Eq for Interface {}
32
33impl std::hash::Hash for Interface {
34 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
35 self.def.hash(state);
36 }
37}
38
39impl Ord for Interface {
40 fn cmp(&self, other: &Self) -> Ordering {
41 (self.def.name(), self.def).cmp(&(other.def.name(), other.def))
42 }
43}
44
45impl PartialOrd for Interface {
46 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
47 Some(self.cmp(other))
48 }
49}
50
51impl Interface {
52 pub fn type_name(&self) -> TypeName {
53 self.def.type_name()
54 }
55
56 pub fn get_methods(&self, writer: &Writer) -> Vec<MethodOrName> {
57 self.def
58 .methods()
59 .map(|def| {
60 let method = Method::new(def, &self.generics);
61 if method.dependencies.included(writer.config) {
62 MethodOrName::Method(method)
63 } else {
64 MethodOrName::Name(method.def.name())
65 }
66 })
67 .collect()
68 }
69
70 pub fn write(&self, writer: &Writer) -> TokenStream {
71 let type_name = self.def.type_name();
72 let methods = self.get_methods(writer);
73
74 let mut required_interfaces = self.required_interfaces();
75 required_interfaces.sort();
76
77 let name = self.write_name(writer);
78
79 let vtbl_name = self.write_vtbl_name(writer);
80 let is_exclusive = self.is_exclusive();
81 let constraints = writer.write_generic_constraints(&self.generics);
82 let phantoms = writer.write_generic_phantoms(&self.generics);
83 let named_phantoms = writer.write_generic_named_phantoms(&self.generics);
84
85 let mut dependencies = TypeMap::new();
86
87 if writer.config.package {
88 self.dependencies(&mut dependencies);
89 }
90
91 let cfg = writer.write_cfg(self.def, self.def.namespace(), &dependencies, false);
92
93 let vtbl = {
94 let virtual_names = &mut MethodNames::new();
95 let core = writer.write_core();
96
97 let vtbl_methods = methods.iter().map(|method| match method {
98 MethodOrName::Method(method) => {
99 let mut difference = TypeMap::new();
100
101 if writer.config.package {
102 difference = method.dependencies.difference(&dependencies);
103 }
104
105 let name = virtual_names.add(method.def);
106 let vtbl = method.write_abi(writer, false);
107 let cfg = writer.write_cfg(self.def, self.def.namespace(), &difference, false);
108
109 if cfg.is_empty() {
110 quote! {
111 pub #name: unsafe extern "system" fn(#vtbl) -> #core HRESULT,
112 }
113 } else {
114 let cfg_not =
115 writer.write_cfg(self.def, self.def.namespace(), &difference, true);
116
117 quote! {
118 #cfg
119 pub #name: unsafe extern "system" fn(#vtbl) -> #core HRESULT,
120 #cfg_not
121 #name: usize,
122 }
123 }
124 }
125 MethodOrName::Name(name) => {
126 let name = to_ident(name);
127 quote! { #name: usize, }
128 }
129 });
130
131 quote! {
132 #cfg
133 #[repr(C)]
134 pub struct #vtbl_name where #constraints {
135 pub base__: #core IInspectable_Vtbl,
136 #(#vtbl_methods)*
137 #named_phantoms
138 }
139 }
140 };
141
142 if writer.config.sys {
143 let mut result = quote! {};
144
145 if !writer.config.package {
146 if let Some(guid) = self.def.guid_attribute() {
147 let name: TokenStream = format!("IID_{}", self.def.name()).into();
148 result.combine(writer.write_cpp_const_guid(name, &guid));
149 }
150
151 result.combine(vtbl);
152 }
153
154 result
155 } else {
156 let mut result = if self.generics.is_empty() {
157 let guid = writer.write_guid_u128(&self.def.guid_attribute().unwrap());
158
159 quote! {
160 #cfg
161 windows_core::imp::define_interface!(#name, #vtbl_name, #guid);
162 #cfg
163 impl windows_core::RuntimeType for #name {
164 const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::for_interface::<Self>();
165 }
166 }
167 } else {
168 let guid = self.def.guid_attribute().unwrap();
169 let pinterface = Literal::byte_string(&format!("pinterface({{{guid}}}"));
170
171 let generics = self.generics.iter().map(|generic| {
172 let name = generic.write_name(writer);
173
174 quote! {
175 .push_slice(b";").push_other(#name::SIGNATURE)
176 }
177 });
178
179 quote! {
180 #[repr(transparent)]
181 #[derive(Clone, Debug, Eq, PartialEq)]
182 pub struct #name(windows_core::IUnknown, #phantoms) where #constraints;
183 impl<#constraints> windows_core::imp::CanInto<windows_core::IUnknown> for #name {}
184 impl<#constraints> windows_core::imp::CanInto<windows_core::IInspectable> for #name {}
185 unsafe impl<#constraints> windows_core::Interface for #name {
186 type Vtable = #vtbl_name;
187 const IID: windows_core::GUID = windows_core::GUID::from_signature(<Self as windows_core::RuntimeType>::SIGNATURE);
188 }
189 impl<#constraints> windows_core::RuntimeType for #name {
190 const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::new().push_slice(#pinterface)#(#generics)*.push_slice(b")");
191 }
192 }
193 };
194
195 if !is_exclusive && self.generics.is_empty() {
196 result.combine(quote! {
197 #cfg
198 windows_core::imp::interface_hierarchy!(#name, windows_core::IUnknown, windows_core::IInspectable);
199 });
200 }
201
202 if !is_exclusive && !required_interfaces.is_empty() {
203 if self.generics.is_empty() {
204 let interfaces = required_interfaces.iter().map(|ty| ty.write_name(writer));
205
206 result.combine(quote! {
207 #cfg
208 windows_core::imp::required_hierarchy!(#name, #(#interfaces),*);
209 });
210 } else {
211 let interfaces = required_interfaces.iter().map(|ty| {
212 let ty = ty.write_name(writer);
213 quote!{
214 impl<#constraints> windows_core::imp::CanInto<#ty> for #name { const QUERY: bool = true; }
215 }
216 });
217
218 result.combine(quote! {
219 #(#interfaces)*
220 });
221 }
222 }
223
224 if !is_exclusive {
225 let method_names = &mut MethodNames::new();
226 let virtual_names = &mut MethodNames::new();
227 let mut method_tokens = TokenStream::new();
228
229 for method in methods.iter().filter_map(|method| match &method {
230 MethodOrName::Method(method) => Some(method),
231 _ => None,
232 }) {
233 let mut difference = TypeMap::new();
234
235 if writer.config.package {
236 difference = method.dependencies.difference(&dependencies);
237 }
238
239 let cfg = writer.write_cfg(self.def, self.def.namespace(), &difference, false);
240
241 let method = method.write(
242 writer,
243 Some(self),
244 InterfaceKind::Default,
245 method_names,
246 virtual_names,
247 );
248
249 method_tokens.combine(quote! {
250 #cfg
251 #method
252 });
253 }
254
255 for interface in &required_interfaces {
256 let virtual_names = &mut MethodNames::new();
257
258 for method in
259 interface
260 .get_methods(writer)
261 .iter()
262 .filter_map(|method| match &method {
263 MethodOrName::Method(method) => Some(method),
264 _ => None,
265 })
266 {
267 let mut difference = TypeMap::new();
268
269 if writer.config.package {
270 difference = method.dependencies.difference(&dependencies);
271 }
272
273 let cfg =
274 writer.write_cfg(self.def, self.def.namespace(), &difference, false);
275
276 let method = method.write(
277 writer,
278 Some(interface),
279 interface.kind,
280 method_names,
281 virtual_names,
282 );
283
284 method_tokens.combine(quote! {
285 #cfg
286 #method
287 });
288 }
289 }
290
291 if !method_tokens.is_empty() {
292 result.combine(quote! {
293 #cfg
294 impl<#constraints> #name {
295 #method_tokens
296 }
297 });
298 }
299
300 if self.def.is_agile() {
301 result.combine(quote! {
302 #cfg
303 unsafe impl<#constraints> Send for #name {}
304 #cfg
305 unsafe impl<#constraints> Sync for #name {}
306 });
307 }
308
309 if let Some(into_iterator) = required_interfaces
310 .iter()
311 .find(|interface| interface.type_name() == TypeName::IIterable)
312 .map(|interface| {
313 let ty = interface.generics[0].write_name(writer);
314 let namespace = writer.write_namespace(TypeName::IIterator);
315
316 quote! {
317 #cfg
318 impl<#constraints> IntoIterator for #name {
319 type Item = #ty;
320 type IntoIter = #namespace IIterator<Self::Item>;
321
322 fn into_iter(self) -> Self::IntoIter {
323 IntoIterator::into_iter(&self)
324 }
325 }
326 #cfg
327 impl<#constraints> IntoIterator for &#name {
328 type Item = #ty;
329 type IntoIter = #namespace IIterator<Self::Item>;
330
331 fn into_iter(self) -> Self::IntoIter {
332 self.First().unwrap()
333 }
334 }
335
336 }
337 })
338 {
339 result.combine(into_iterator);
340 }
341 }
342
343 if writer.config.implement || !is_exclusive {
344 let impl_name: TokenStream = format!("{}_Impl", self.def.name()).into();
345
346 let generics: Vec<_> = self
347 .generics
348 .iter()
349 .map(|ty| ty.write_name(writer))
350 .collect();
351
352 let runtime_name = format!("{type_name}");
353
354 if writer.config.package {
355 fn collect(interface: &Interface, dependencies: &mut TypeMap, writer: &Writer) {
356 for method in interface.get_methods(writer).iter() {
357 if let MethodOrName::Method(method) = method {
358 dependencies.combine(&method.dependencies);
359 }
360 }
361 }
362
363 collect(self, &mut dependencies, writer);
364 required_interfaces
365 .iter()
366 .for_each(|interface| collect(interface, &mut dependencies, writer));
367 }
368
369 let cfg = writer.write_cfg(self.def, self.def.namespace(), &dependencies, false);
370
371 result.combine(quote! {
372 #cfg
373 impl<#constraints> windows_core::RuntimeName for #name {
374 const NAME: &'static str = #runtime_name;
375 }
376 });
377
378 let mut names = MethodNames::new();
379
380 let field_methods: Vec<_> = methods
381 .iter()
382 .map(|method| match method {
383 MethodOrName::Method(method) => {
384 let name = names.add(method.def);
385 quote! { #name: #name::<#(#generics,)* Identity, OFFSET>, }
386 }
387 MethodOrName::Name(name) => {
388 let name = to_ident(name);
389 quote! { #name: 0, }
390 }
391 })
392 .collect();
393
394 let mut names = MethodNames::new();
395
396 let impl_methods: Vec<_> = methods.iter().map(|method| match method {
397 MethodOrName::Method(method) => {
398 let name = names.add(method.def);
399 let signature = method.write_abi(writer, true);
400 let call = quote! { #impl_name::#name };
401 let upcall = method.write_upcall(call, true);
402
403 quote! {
404 unsafe extern "system" fn #name<#constraints Identity: #impl_name <#(#generics,)*>, const OFFSET: isize> (#signature) -> windows_core::HRESULT {
405 unsafe {
406 let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity);
407 #upcall
408 }
409 }
410 }
411 }
412 _ => quote! {},
413 }).collect();
414
415 let mut names = MethodNames::new();
416
417 let trait_methods: Vec<_> = methods
418 .iter()
419 .map(|method| match method {
420 MethodOrName::Method(method) => {
421 let name = names.add(method.def);
422 let signature = method.write_impl_signature(writer, true, true);
423 quote! { fn #name #signature; }
424 }
425 _ => quote! {},
426 })
427 .collect();
428
429 let requires = if required_interfaces.is_empty() {
430 quote! { windows_core::IUnknownImpl }
431 } else {
432 let interfaces = required_interfaces
433 .iter()
434 .map(|ty| ty.write_impl_name(writer));
435
436 quote! { #(#interfaces)+* }
437 };
438
439 result.combine(quote! {
440 #cfg
441 pub trait #impl_name <#(#generics),*> : #requires where #constraints {
442 #(#trait_methods)*
443 }
444 #cfg
445 impl<#constraints> #vtbl_name {
446 pub const fn new<Identity: #impl_name <#(#generics,)*>, const OFFSET: isize>() -> Self {
447 #(#impl_methods)*
448 Self {
449 base__: windows_core::IInspectable_Vtbl::new::<Identity, #name, OFFSET>(),
450 #(#field_methods)*
451 #named_phantoms
452 }
453 }
454 pub fn matches(iid: &windows_core::GUID) -> bool {
455 iid == &<#name as windows_core::Interface>::IID
456 }
457 }
458 });
459 }
460
461 result.combine(vtbl);
462 result.combine(self.write_extensions());
463 result
464 }
465 }
466
467 fn write_extensions(&self) -> TokenStream {
468 match self.type_name() {
469 TypeName::IIterator => {
470 quote! {
471 impl<T: windows_core::RuntimeType> Iterator for IIterator<T> {
472 type Item = T;
473
474 fn next(&mut self) -> Option<Self::Item> {
475 let result = self.Current().ok();
476
477 if result.is_some() {
478 self.MoveNext().ok()?;
479 }
480
481 result
482 }
483 }
484 }
485 }
486 TypeName::IIterable => {
487 quote! {
488 impl<T: windows_core::RuntimeType> IntoIterator for IIterable<T> {
489 type Item = T;
490 type IntoIter = IIterator<Self::Item>;
491
492 fn into_iter(self) -> Self::IntoIter {
493 IntoIterator::into_iter(&self)
494 }
495 }
496 impl<T: windows_core::RuntimeType> IntoIterator for &IIterable<T> {
497 type Item = T;
498 type IntoIter = IIterator<Self::Item>;
499
500 fn into_iter(self) -> Self::IntoIter {
501 self.First().unwrap()
502 }
503 }
504
505 }
506 }
507 _ => quote! {},
508 }
509 }
510
511 pub fn write_name(&self, writer: &Writer) -> TokenStream {
512 if writer.config.sys {
513 quote! { *mut core::ffi::c_void }
514 } else {
515 self.type_name().write(writer, &self.generics)
516 }
517 }
518
519 fn write_vtbl_name(&self, writer: &Writer) -> TokenStream {
520 let name: TokenStream = format!("{}_Vtbl", self.def.name()).into();
521
522 if self.generics.is_empty() {
523 name
524 } else {
525 let generics = self.generics.iter().map(|ty| ty.write_name(writer));
526 quote! { #name < #(#generics,)* > }
527 }
528 }
529
530 pub fn write_impl_name(&self, writer: &Writer) -> TokenStream {
531 let name: TokenStream = format!("{}_Impl", self.def.name()).into();
532 let namespace = writer.write_namespace(self.def.type_name());
533
534 if self.generics.is_empty() {
535 quote! { #namespace #name }
536 } else {
537 let generics = self.generics.iter().map(|ty| ty.write_name(writer));
538 quote! { #namespace #name < #(#generics),* > }
539 }
540 }
541
542 pub fn is_exclusive(&self) -> bool {
543 self.def.has_attribute("ExclusiveToAttribute")
544 }
545
546 pub fn runtime_signature(&self) -> String {
547 interface_signature(self.def, &self.generics)
548 }
549
550 pub fn dependencies(&self, dependencies: &mut TypeMap) {
551 Type::Object.dependencies(dependencies);
552
553 for interface in self.required_interfaces() {
554 Type::Interface(interface).dependencies(dependencies);
555 }
556
557 // Different specializations of Interface may have different generics...
558 for ty in &self.generics {
559 ty.dependencies(dependencies);
560 }
561
562 let is_iterable = self.type_name() == TypeName::IIterable;
563
564 for method in self.def.methods() {
565 for ty in method
566 .signature(self.def.namespace(), &self.generics)
567 .types()
568 {
569 if is_iterable || ty.is_core() {
570 ty.dependencies(dependencies);
571 }
572 }
573 }
574 }
575
576 pub fn required_interfaces(&self) -> Vec<Self> {
577 fn walk(interface: &Interface, set: &mut Vec<Interface>) {
578 for ty in interface
579 .def
580 .interface_impls()
581 .map(|imp| imp.ty(&interface.generics))
582 {
583 let Type::Interface(interface) = ty else {
584 panic!();
585 };
586
587 if !set.iter().any(|existing| existing.def == interface.def) {
588 walk(&interface, set);
589 set.push(interface);
590 }
591 }
592 }
593 let mut set = vec![];
594 walk(self, &mut set);
595 set
596 }
597}
598