summaryrefslogtreecommitdiffstats
path: root/vendor/windows-bindgen/src/delegates.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/windows-bindgen/src/delegates.rs')
-rw-r--r--vendor/windows-bindgen/src/delegates.rs181
1 files changed, 181 insertions, 0 deletions
diff --git a/vendor/windows-bindgen/src/delegates.rs b/vendor/windows-bindgen/src/delegates.rs
new file mode 100644
index 000000000..a68719c81
--- /dev/null
+++ b/vendor/windows-bindgen/src/delegates.rs
@@ -0,0 +1,181 @@
+use super::*;
+
+pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream {
+ if gen
+ .reader
+ .type_def_flags(def)
+ .contains(TypeAttributes::WINRT)
+ {
+ gen_delegate(gen, def)
+ } else {
+ gen_callback(gen, def)
+ }
+}
+
+fn gen_callback(gen: &Gen, def: TypeDef) -> TokenStream {
+ let name = to_ident(gen.reader.type_def_name(def));
+
+ let method = gen.reader.type_def_invoke_method(def);
+ let signature = gen.reader.method_def_signature(method, &[]);
+ let return_type = gen.return_sig(&signature);
+ let cfg = gen.reader.type_def_cfg(def, &[]);
+ let doc = gen.cfg_doc(&cfg);
+ let features = gen.cfg_features(&cfg);
+
+ let params = signature.params.iter().map(|p| {
+ let name = gen.param_name(p.def);
+ let tokens = gen.type_default_name(&p.ty);
+ quote! { #name: #tokens }
+ });
+
+ quote! {
+ #doc
+ #features
+ pub type #name = ::core::option::Option<unsafe extern "system" fn(#(#params),*) #return_type>;
+ }
+}
+
+fn gen_delegate(gen: &Gen, def: TypeDef) -> TokenStream {
+ if gen.sys {
+ let name = to_ident(gen.reader.type_def_name(def));
+ quote! {
+ pub type #name = *mut ::core::ffi::c_void;
+ }
+ } else {
+ gen_win_delegate(gen, def)
+ }
+}
+
+fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream {
+ let name = to_ident(gen.reader.type_def_name(def));
+ let vtbl = name.join("_Vtbl");
+ let boxed = name.join("Box");
+
+ let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect();
+ let phantoms = gen.generic_phantoms(generics);
+ let named_phantoms = gen.generic_named_phantoms(generics);
+ let constraints = gen.generic_constraints(generics);
+ let generic_names = gen.generic_names(generics);
+
+ let ident = gen.type_def_name(def, generics);
+
+ let method = gen.reader.type_def_invoke_method(def);
+ let signature = gen.reader.method_def_signature(method, generics);
+ let fn_constraint = gen_fn_constraint(gen, def, &signature);
+
+ let cfg = gen.reader.type_def_cfg(def, generics);
+ let doc = gen.cfg_doc(&cfg);
+ let features = gen.cfg_features(&cfg);
+
+ let vtbl_signature = gen.vtbl_signature(def, generics, &signature);
+ let invoke = winrt_methods::gen(
+ gen,
+ def,
+ generics,
+ InterfaceKind::Default,
+ method,
+ &mut MethodNames::new(),
+ &mut MethodNames::new(),
+ );
+ let invoke_upcall = winrt_methods::gen_upcall(gen, &signature, quote! { ((*this).invoke) });
+
+ let mut tokens = quote! {
+ #doc
+ #features
+ #[repr(transparent)]
+ pub struct #ident(pub ::windows::core::IUnknown, #phantoms) where #constraints;
+ #features
+ impl<#constraints> #ident {
+ pub fn new<#fn_constraint>(invoke: F) -> Self {
+ let com = #boxed::<#generic_names F> {
+ vtable: &#boxed::<#generic_names F>::VTABLE,
+ count: ::windows::imp::RefCount::new(1),
+ invoke,
+ };
+ unsafe {
+ ::core::mem::transmute(::std::boxed::Box::new(com))
+ }
+ }
+ #invoke
+ }
+ #features
+ #[repr(C)]
+ struct #boxed<#generic_names #fn_constraint> where #constraints {
+ vtable: *const #vtbl<#generic_names>,
+ invoke: F,
+ count: ::windows::imp::RefCount,
+ }
+ #features
+ impl<#constraints #fn_constraint> #boxed<#generic_names F> {
+ const VTABLE: #vtbl<#generic_names> = #vtbl::<#generic_names>{
+ base__: ::windows::core::IUnknown_Vtbl{QueryInterface: Self::QueryInterface, AddRef: Self::AddRef, Release: Self::Release},
+ Invoke: Self::Invoke,
+ #(#named_phantoms)*
+ };
+ unsafe extern "system" fn QueryInterface(this: *mut ::core::ffi::c_void, iid: &::windows::core::GUID, interface: *mut *const ::core::ffi::c_void) -> ::windows::core::HRESULT {
+ let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
+
+ *interface = if iid == &<#ident as ::windows::core::ComInterface>::IID ||
+ iid == &<::windows::core::IUnknown as ::windows::core::ComInterface>::IID ||
+ iid == &<::windows::imp::IAgileObject as ::windows::core::ComInterface>::IID {
+ &mut (*this).vtable as *mut _ as _
+ } else {
+ ::core::ptr::null_mut()
+ };
+
+ // TODO: implement IMarshal
+
+ if (*interface).is_null() {
+ ::windows::core::HRESULT(-2147467262) // E_NOINTERFACE
+ } else {
+ (*this).count.add_ref();
+ ::windows::core::HRESULT(0)
+ }
+ }
+ unsafe extern "system" fn AddRef(this: *mut ::core::ffi::c_void) -> u32 {
+ let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
+ (*this).count.add_ref()
+ }
+ unsafe extern "system" fn Release(this: *mut ::core::ffi::c_void) -> u32 {
+ let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
+ let remaining = (*this).count.release();
+
+ if remaining == 0 {
+ let _ = ::std::boxed::Box::from_raw(this);
+ }
+
+ remaining
+ }
+ unsafe extern "system" fn Invoke #vtbl_signature {
+ let this = this as *mut *mut ::core::ffi::c_void as *mut Self;
+ #invoke_upcall
+ }
+ }
+ };
+
+ tokens.combine(&gen.interface_core_traits(
+ def,
+ generics,
+ &ident,
+ &constraints,
+ &phantoms,
+ &features,
+ ));
+ tokens.combine(&gen.interface_trait(def, generics, &ident, &constraints, &features, true));
+ tokens.combine(&gen.interface_winrt_trait(
+ def,
+ generics,
+ &ident,
+ &constraints,
+ &phantoms,
+ &features,
+ ));
+ tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features));
+ tokens
+}
+
+fn gen_fn_constraint(gen: &Gen, def: TypeDef, signature: &Signature) -> TokenStream {
+ let signature = gen.impl_signature(def, signature);
+
+ quote! { F: FnMut #signature + ::core::marker::Send + 'static }
+}