]> git.proxmox.com Git - rustc.git/blob - vendor/windows-bindgen/src/rust/delegates.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / vendor / windows-bindgen / src / rust / delegates.rs
1 use super::*;
2
3 pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream {
4 if def.flags().contains(TypeAttributes::WindowsRuntime) {
5 gen_delegate(writer, def)
6 } else {
7 gen_callback(writer, def)
8 }
9 }
10
11 fn gen_callback(writer: &Writer, def: TypeDef) -> TokenStream {
12 let name = to_ident(def.name());
13 let method = type_def_invoke_method(def);
14
15 let signature = method_def_signature(def.namespace(), method, &[]);
16
17 let return_type = writer.return_sig(&signature);
18 let cfg = type_def_cfg(def, &[]);
19 let doc = writer.cfg_doc(&cfg);
20 let features = writer.cfg_features(&cfg);
21
22 let params = signature.params.iter().map(|p| {
23 let name = writer.param_name(p.def);
24 let tokens = writer.type_default_name(&p.ty);
25 quote! { #name: #tokens }
26 });
27
28 quote! {
29 #doc
30 #features
31 pub type #name = ::core::option::Option<unsafe extern "system" fn(#(#params),*) #return_type>;
32 }
33 }
34
35 fn gen_delegate(writer: &Writer, def: TypeDef) -> TokenStream {
36 if writer.sys {
37 let name = to_ident(def.name());
38 quote! {
39 pub type #name = *mut ::core::ffi::c_void;
40 }
41 } else {
42 gen_win_delegate(writer, def)
43 }
44 }
45
46 fn gen_win_delegate(writer: &Writer, def: TypeDef) -> TokenStream {
47 let name = to_ident(def.name());
48 let vtbl = name.join("_Vtbl");
49 let boxed = name.join("Box");
50
51 let generics = &type_def_generics(def);
52 let phantoms = writer.generic_phantoms(generics);
53 let named_phantoms = writer.generic_named_phantoms(generics);
54 let constraints = writer.generic_constraints(generics);
55 let generic_names = writer.generic_names(generics);
56
57 let ident = writer.type_def_name(def, generics);
58 let method = type_def_invoke_method(def);
59
60 let signature = method_def_signature(def.namespace(), method, generics);
61
62 let fn_constraint = gen_fn_constraint(writer, def, &signature);
63 let cfg = type_def_cfg(def, generics);
64 let doc = writer.cfg_doc(&cfg);
65 let features = writer.cfg_features(&cfg);
66
67 let vtbl_signature = writer.vtbl_signature(def, generics, &signature);
68 let invoke = winrt_methods::writer(writer, def, generics, InterfaceKind::Default, method, &mut MethodNames::new(), &mut MethodNames::new());
69 let invoke_upcall = winrt_methods::gen_upcall(writer, &signature, quote! { ((*this).invoke) });
70
71 let mut tokens = quote! {
72 #doc
73 #features
74 #[repr(transparent)]
75 #[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
76 pub struct #ident(pub ::windows_core::IUnknown, #phantoms) where #constraints;
77 #features
78 impl<#constraints> #ident {
79 pub fn new<#fn_constraint>(invoke: F) -> Self {
80 let com = #boxed::<#generic_names F> {
81 vtable: &#boxed::<#generic_names F>::VTABLE,
82 count: ::windows_core::imp::RefCount::new(1),
83 invoke,
84 };
85 unsafe {
86 ::core::mem::transmute(::std::boxed::Box::new(com))
87 }
88 }
89 #invoke
90 }
91 #features
92 #[repr(C)]
93 struct #boxed<#generic_names #fn_constraint> where #constraints {
94 vtable: *const #vtbl<#generic_names>,
95 invoke: F,
96 count: ::windows_core::imp::RefCount,
97 }
98 #features
99 impl<#constraints #fn_constraint> #boxed<#generic_names F> {
100 const VTABLE: #vtbl<#generic_names> = #vtbl::<#generic_names>{
101 base__: ::windows_core::IUnknown_Vtbl{QueryInterface: Self::QueryInterface, AddRef: Self::AddRef, Release: Self::Release},
102 Invoke: Self::Invoke,
103 #(#named_phantoms)*
104 };
105 unsafe extern "system" fn QueryInterface(this: *mut ::core::ffi::c_void, iid: *const ::windows_core::GUID, interface: *mut *mut ::core::ffi::c_void) -> ::windows_core::HRESULT {
106 let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
107
108 if iid.is_null() || interface.is_null() {
109 return ::windows_core::HRESULT(-2147467261); // E_POINTER
110 }
111
112 *interface = if *iid == <#ident as ::windows_core::ComInterface>::IID ||
113 *iid == <::windows_core::IUnknown as ::windows_core::ComInterface>::IID ||
114 *iid == <::windows_core::imp::IAgileObject as ::windows_core::ComInterface>::IID {
115 &mut (*this).vtable as *mut _ as _
116 } else {
117 ::core::ptr::null_mut()
118 };
119
120 // TODO: implement IMarshal
121
122 if (*interface).is_null() {
123 ::windows_core::HRESULT(-2147467262) // E_NOINTERFACE
124 } else {
125 (*this).count.add_ref();
126 ::windows_core::HRESULT(0)
127 }
128 }
129 unsafe extern "system" fn AddRef(this: *mut ::core::ffi::c_void) -> u32 {
130 let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
131 (*this).count.add_ref()
132 }
133 unsafe extern "system" fn Release(this: *mut ::core::ffi::c_void) -> u32 {
134 let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
135 let remaining = (*this).count.release();
136
137 if remaining == 0 {
138 let _ = ::std::boxed::Box::from_raw(this);
139 }
140
141 remaining
142 }
143 unsafe extern "system" fn Invoke #vtbl_signature {
144 let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
145 #invoke_upcall
146 }
147 }
148 };
149
150 tokens.combine(&writer.interface_trait(def, generics, &ident, &constraints, &features, true));
151 tokens.combine(&writer.interface_winrt_trait(def, generics, &ident, &constraints, &phantoms, &features));
152 tokens.combine(&writer.interface_vtbl(def, generics, &ident, &constraints, &features));
153 tokens
154 }
155
156 fn gen_fn_constraint(writer: &Writer, def: TypeDef, signature: &Signature) -> TokenStream {
157 let signature = writer.impl_signature(def, signature);
158
159 quote! { F: FnMut #signature + ::core::marker::Send + 'static }
160 }