]> git.proxmox.com Git - rustc.git/blob - vendor/windows-bindgen/src/functions.rs
New upstream version 1.73.0+dfsg1
[rustc.git] / vendor / windows-bindgen / src / functions.rs
1 use super::*;
2
3 pub fn gen(gen: &Gen, def: MethodDef) -> TokenStream {
4 if gen.sys {
5 gen_sys_function(gen, def)
6 } else {
7 gen_win_function(gen, def)
8 }
9 }
10
11 fn gen_sys_function(gen: &Gen, def: MethodDef) -> TokenStream {
12 let signature = gen.reader.method_def_signature(def, &[]);
13 let cfg = gen.reader.signature_cfg(&signature);
14 let mut tokens = gen.cfg_features(&cfg);
15 tokens.combine(&gen_link(gen, &signature, &cfg));
16 tokens
17 }
18
19 fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
20 let name = to_ident(gen.reader.method_def_name(def));
21 let signature = gen.reader.method_def_signature(def, &[]);
22 let generics = gen.constraint_generics(&signature.params);
23 let where_clause = gen.where_clause(&signature.params);
24 let abi_return_type = gen.return_sig(&signature);
25 let cfg = gen.reader.signature_cfg(&signature);
26 let doc = gen.cfg_doc(&cfg);
27 let features = gen.cfg_features(&cfg);
28 let link = gen_link(gen, &signature, &cfg);
29
30 let kind = gen.reader.signature_kind(&signature);
31 match kind {
32 SignatureKind::Query(_) => {
33 let args = gen.win32_args(&signature.params, kind);
34 let params = gen.win32_params(&signature.params, kind);
35 let generics = expand_generics(generics, quote!(T));
36 let where_clause =
37 expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface));
38
39 quote! {
40 #doc
41 #features
42 #[inline]
43 pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<T> #where_clause {
44 #link
45 let mut result__ = ::std::ptr::null_mut();
46 #name(#args).from_abi(result__)
47 }
48 }
49 }
50 SignatureKind::QueryOptional(_) => {
51 let args = gen.win32_args(&signature.params, kind);
52 let params = gen.win32_params(&signature.params, kind);
53 let generics = expand_generics(generics, quote!(T));
54 let where_clause =
55 expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface));
56
57 quote! {
58 #doc
59 #features
60 #[inline]
61 pub unsafe fn #name<#generics>(#params result__: *mut ::core::option::Option<T>) -> ::windows::core::Result<()> #where_clause {
62 #link
63 #name(#args).ok()
64 }
65 }
66 }
67 SignatureKind::ResultValue => {
68 let args = gen.win32_args(&signature.params, kind);
69 let params = gen.win32_params(&signature.params, kind);
70 let return_type = signature.params[signature.params.len() - 1].ty.deref();
71 let return_type = gen.type_name(&return_type);
72
73 quote! {
74 #doc
75 #features
76 #[inline]
77 pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause {
78 #link
79 let mut result__ = ::windows::core::zeroed::<#return_type>();
80 #name(#args).from_abi(result__)
81 }
82 }
83 }
84 SignatureKind::ResultVoid => {
85 let args = gen.win32_args(&signature.params, kind);
86 let params = gen.win32_params(&signature.params, kind);
87
88 quote! {
89 #doc
90 #features
91 #[inline]
92 pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<()> #where_clause {
93 #link
94 #name(#args).ok()
95 }
96 }
97 }
98 SignatureKind::ReturnValue => {
99 let args = gen.win32_args(&signature.params, kind);
100 let params = gen.win32_params(&signature.params, kind);
101 let return_type = signature.params[signature.params.len() - 1].ty.deref();
102 let is_nullable = gen.reader.type_is_nullable(&return_type);
103 let return_type = gen.type_name(&return_type);
104
105 if is_nullable {
106 quote! {
107 #doc
108 #features
109 #[inline]
110 pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause {
111 #link
112 let mut result__ = ::windows::core::zeroed::<#return_type>();
113 #name(#args);
114 ::windows::core::from_abi(result__.assume_init())
115 }
116 }
117 } else {
118 quote! {
119 #doc
120 #features
121 #[inline]
122 pub unsafe fn #name<#generics>(#params) -> #return_type #where_clause {
123 #link
124 let mut result__ = ::windows::core::zeroed::<#return_type>();
125 #name(#args);
126 ::std::mem::transmute(result__)
127 }
128 }
129 }
130 }
131 SignatureKind::ReturnStruct | SignatureKind::PreserveSig => {
132 if handle_last_error(gen, def, &signature) {
133 let args = gen.win32_args(&signature.params, kind);
134 let params = gen.win32_params(&signature.params, kind);
135 let return_type = gen.type_name(&signature.return_type.unwrap());
136
137 quote! {
138 #doc
139 #features
140 #[inline]
141 pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause {
142 #link
143 let result__ = #name(#args);
144 ::windows::imp::then(!result__.is_invalid(), ||result__).ok_or_else(::windows::core::Error::from_win32)
145 }
146 }
147 } else {
148 let args = gen.win32_args(&signature.params, kind);
149 let params = gen.win32_params(&signature.params, kind);
150
151 quote! {
152 #doc
153 #features
154 #[inline]
155 pub unsafe fn #name<#generics>(#params) #abi_return_type #where_clause {
156 #link
157 #name(#args)
158 }
159 }
160 }
161 }
162 SignatureKind::ReturnVoid => {
163 let args = gen.win32_args(&signature.params, kind);
164 let params = gen.win32_params(&signature.params, kind);
165 let does_not_return = does_not_return(gen, def);
166
167 quote! {
168 #doc
169 #features
170 #[inline]
171 pub unsafe fn #name<#generics>(#params) #does_not_return #where_clause {
172 #link
173 #name(#args)
174 }
175 }
176 }
177 }
178 }
179
180 fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream {
181 let name = gen.reader.method_def_name(signature.def);
182 let ident = to_ident(name);
183 let library = gen.reader.method_def_module_name(signature.def);
184 let abi = gen.reader.method_def_extern_abi(signature.def);
185
186 let symbol = if let Some(impl_map) = gen.reader.method_def_impl_map(signature.def) {
187 gen.reader.impl_map_import_name(impl_map)
188 } else {
189 name
190 };
191
192 let link_name = if symbol != name {
193 quote! { #[link_name = #symbol] }
194 } else {
195 quote! {}
196 };
197
198 let params = signature.params.iter().map(|p| {
199 let name = gen.param_name(p.def);
200 let tokens = if p.kind == SignatureParamKind::ValueType {
201 gen.type_default_name(&p.ty)
202 } else {
203 gen.type_abi_name(&p.ty)
204 };
205 quote! { #name: #tokens }
206 });
207
208 let return_type = gen.return_sig(signature);
209
210 if gen.std || !gen.namespace.starts_with("Windows.") {
211 let library = library.trim_end_matches(".dll");
212
213 quote! {
214 #[link(name = #library)]
215 extern #abi {
216 #link_name
217 pub fn #ident(#(#params),*) #return_type;
218 }
219 }
220 } else if let Some(library) = gen.reader.method_def_static_lib(signature.def) {
221 quote! {
222 #[link(name = #library, kind = "static")]
223 extern #abi {
224 #link_name
225 pub fn #ident(#(#params),*) #return_type;
226 }
227 }
228 } else {
229 let symbol = if symbol != name {
230 format!(" \"{symbol}\"")
231 } else {
232 String::new()
233 };
234
235 let doc = if gen.sys {
236 gen.cfg_doc(cfg).0
237 } else {
238 String::new()
239 };
240
241 let mut tokens = String::new();
242 for param in params {
243 tokens.push_str(&format!("{}, ", param.as_str()));
244 }
245 let tokens = tokens.trim_end_matches(", ");
246 format!(
247 r#"::windows_targets::link!("{library}" "{abi}"{symbol}{doc} fn {name}({tokens}){return_type});"#
248 )
249 .into()
250 }
251 }
252
253 fn does_not_return(gen: &Gen, def: MethodDef) -> TokenStream {
254 if gen.reader.method_def_does_not_return(def) {
255 quote! { -> ! }
256 } else {
257 quote! {}
258 }
259 }
260
261 fn handle_last_error(gen: &Gen, def: MethodDef, signature: &Signature) -> bool {
262 if let Some(map) = gen.reader.method_def_impl_map(def) {
263 if gen
264 .reader
265 .impl_map_flags(map)
266 .contains(PInvokeAttributes::LAST_ERROR)
267 {
268 if let Some(Type::TypeDef((return_type, _))) = &signature.return_type {
269 if gen.reader.type_def_is_handle(*return_type) {
270 if gen
271 .reader
272 .type_def_underlying_type(*return_type)
273 .is_pointer()
274 {
275 return true;
276 }
277 if !gen.reader.type_def_invalid_values(*return_type).is_empty() {
278 return true;
279 }
280 }
281 }
282 }
283 }
284 false
285 }