]> git.proxmox.com Git - rustc.git/blob - vendor/windows-bindgen/src/interfaces.rs
New upstream version 1.73.0+dfsg1
[rustc.git] / vendor / windows-bindgen / src / interfaces.rs
1 use super::*;
2
3 pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream {
4 if gen.sys {
5 gen_sys_interface(gen, def)
6 } else {
7 gen_win_interface(gen, def)
8 }
9 }
10
11 fn gen_sys_interface(gen: &Gen, def: TypeDef) -> TokenStream {
12 let name = gen.reader.type_def_name(def);
13 let ident = to_ident(name);
14
15 if gen.reader.type_def_is_exclusive(def) {
16 quote! {}
17 } else {
18 quote! {
19 pub type #ident = *mut ::core::ffi::c_void;
20 }
21 }
22 }
23
24 fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream {
25 let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect();
26 let ident = gen.type_def_name(def, generics);
27 let is_exclusive = gen.reader.type_def_is_exclusive(def);
28 let phantoms = gen.generic_phantoms(generics);
29 let constraints = gen.generic_constraints(generics);
30 let cfg = gen.reader.type_def_cfg(def, &[]);
31 let doc = gen.cfg_doc(&cfg);
32 let features = gen.cfg_features(&cfg);
33 let interfaces = gen
34 .reader
35 .type_interfaces(&Type::TypeDef((def, generics.to_vec())));
36 let vtables = gen.reader.type_def_vtables(def);
37 let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown));
38
39 let mut tokens = if is_exclusive {
40 quote! { #[doc(hidden)] }
41 } else {
42 quote! { #doc }
43 };
44
45 if has_unknown_base {
46 tokens.combine(&quote! {
47 #features
48 #[repr(transparent)]
49 pub struct #ident(::windows::core::IUnknown, #phantoms) where #constraints;
50 });
51 } else {
52 tokens.combine(&quote! {
53 #features
54 #[repr(transparent)]
55 pub struct #ident(::std::ptr::NonNull<::std::ffi::c_void>);
56 });
57 }
58
59 if !is_exclusive {
60 let mut methods = quote! {};
61 // We need to distinguish between public and virtual methods because some WinRT type hierarchies inherit colliding (overloaded)
62 // methods that must be distinguishable.
63 let method_names = &mut MethodNames::new();
64 let virtual_names = &mut MethodNames::new();
65
66 if gen
67 .reader
68 .type_def_flags(def)
69 .contains(TypeAttributes::WINRT)
70 {
71 for method in gen.reader.type_def_methods(def) {
72 methods.combine(&winrt_methods::gen(
73 gen,
74 def,
75 generics,
76 InterfaceKind::Default,
77 method,
78 method_names,
79 virtual_names,
80 ));
81 }
82 for interface in &interfaces {
83 if let Type::TypeDef((def, generics)) = &interface.ty {
84 for method in gen.reader.type_def_methods(*def) {
85 methods.combine(&winrt_methods::gen(
86 gen,
87 *def,
88 generics,
89 InterfaceKind::None,
90 method,
91 method_names,
92 virtual_names,
93 ));
94 }
95 }
96 }
97 } else {
98 let mut bases = vtables.len();
99 for ty in &vtables {
100 match ty {
101 Type::IUnknown | Type::IInspectable => {}
102 Type::TypeDef((def, _)) => {
103 let kind = if gen.reader.type_def_type_name(*def) == TypeName::IDispatch {
104 InterfaceKind::None
105 } else {
106 InterfaceKind::Default
107 };
108 for method in gen.reader.type_def_methods(*def) {
109 methods.combine(&com_methods::gen(
110 gen,
111 *def,
112 kind,
113 method,
114 method_names,
115 virtual_names,
116 bases,
117 ));
118 }
119 }
120 _ => unimplemented!(),
121 }
122
123 bases -= 1;
124 }
125 for method in gen.reader.type_def_methods(def) {
126 methods.combine(&com_methods::gen(
127 gen,
128 def,
129 InterfaceKind::Default,
130 method,
131 method_names,
132 virtual_names,
133 0,
134 ));
135 }
136 }
137
138 tokens.combine(&quote! {
139 #features
140 impl<#constraints> #ident {
141 #methods
142 }
143 });
144
145 if !vtables.is_empty() && generics.is_empty() {
146 let mut hierarchy = format!("::windows::imp::interface_hierarchy!({ident}");
147 let mut hierarchy_cfg = cfg.clone();
148
149 for ty in &vtables {
150 let into = gen.type_name(ty);
151
152 write!(&mut hierarchy, ", {into}").unwrap();
153 hierarchy_cfg = hierarchy_cfg.union(&gen.reader.type_cfg(ty));
154 }
155
156 hierarchy.push_str(");");
157 tokens.combine(&gen.cfg_features(&hierarchy_cfg));
158 tokens.push_str(&hierarchy);
159 } else {
160 for ty in &vtables {
161 let into = gen.type_name(ty);
162 let cfg = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(ty)));
163 tokens.combine(&quote! {
164 #cfg
165 impl<#constraints> windows::core::CanInto<#into> for #ident {}
166 });
167 }
168 }
169
170 if gen
171 .reader
172 .type_def_flags(def)
173 .contains(TypeAttributes::WINRT)
174 {
175 for interface in &interfaces {
176 let into = gen.type_name(&interface.ty);
177 let cfg = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty)));
178 tokens.combine(&quote! {
179 #cfg
180 impl<#constraints> windows::core::CanTryInto<#into> for #ident {}
181 });
182 }
183 }
184
185 tokens.combine(&gen.interface_core_traits(
186 def,
187 generics,
188 &ident,
189 &constraints,
190 &phantoms,
191 &features,
192 ));
193 tokens.combine(&gen.interface_winrt_trait(
194 def,
195 generics,
196 &ident,
197 &constraints,
198 &phantoms,
199 &features,
200 ));
201 tokens.combine(&gen.async_get(def, generics, &ident, &constraints, &phantoms, &features));
202 tokens.combine(&iterators::gen(
203 gen,
204 def,
205 generics,
206 &ident,
207 &constraints,
208 &phantoms,
209 &cfg,
210 ));
211 tokens.combine(&gen.agile(def, &ident, &constraints, &features));
212 }
213
214 tokens.combine(&gen.interface_trait(
215 def,
216 generics,
217 &ident,
218 &constraints,
219 &features,
220 has_unknown_base,
221 ));
222 tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features));
223 tokens
224 }