3 pub fn writer(writer
: &Writer
, def
: TypeDef
) -> TokenStream
{
4 if writer
.reader
.type_def_kind(def
) != TypeKind
::Interface
|| (!writer
.implement
&& writer
.reader
.has_attribute(def
, "ExclusiveToAttribute")) {
8 let generics
= &type_def_generics(writer
.reader
, def
);
9 let type_ident
= to_ident(writer
.reader
.type_def_name(def
));
10 let impl_ident
= type_ident
.join("_Impl");
11 let vtbl_ident
= type_ident
.join("_Vtbl");
12 let implvtbl_ident
= impl_ident
.join("Vtbl");
13 let constraints
= writer
.generic_constraints(generics
);
14 let generic_names
= writer
.generic_names(generics
);
15 let named_phantoms
= writer
.generic_named_phantoms(generics
);
16 let cfg
= type_def_cfg_impl(writer
.reader
, def
, generics
);
17 let doc
= writer
.cfg_doc(&cfg
);
18 let features
= writer
.cfg_features(&cfg
);
19 let mut requires
= quote
! {}
;
20 let type_ident
= quote
! { #type_ident<#generic_names> }
;
21 let vtables
= type_def_vtables(writer
.reader
, def
);
22 let has_unknown_base
= matches
!(vtables
.first(), Some(Type
::IUnknown
));
24 fn gen_required_trait(writer
: &Writer
, def
: TypeDef
, generics
: &[Type
]) -> TokenStream
{
25 let name
= writer
.type_def_name_imp(def
, generics
, "_Impl");
31 let mut matches
= quote
! { iid == &<#type_ident as ::windows_core::ComInterface>::IID }
;
33 if let Some(Type
::TypeDef(def
, _
)) = vtables
.last() {
34 requires
.combine(&gen_required_trait(writer
, *def
, &[]))
38 if let Type
::TypeDef(def
, generics
) = def
{
39 let name
= writer
.type_def_name(*def
, generics
);
41 matches
.combine("e
! {
42 || iid
== &<#name as ::windows_core::ComInterface>::IID
47 if writer
.reader
.type_def_flags(def
).contains(TypeAttributes
::WindowsRuntime
) {
48 // TODO: this awkward wrapping of TypeDefs needs fixing
49 for interface
in type_interfaces(writer
.reader
, &Type
::TypeDef(def
, generics
.to_vec())) {
50 if let Type
::TypeDef(def
, generics
) = interface
.ty
{
51 requires
.combine(&gen_required_trait(writer
, def
, &generics
));
56 let runtime_name
= writer
.runtime_name_trait(def
, generics
, &type_ident
, &constraints
, &features
);
58 let mut method_names
= MethodNames
::new();
59 method_names
.add_vtable_types(writer
, def
);
61 let method_traits
= writer
.reader
.type_def_methods(def
).map(|method
| {
62 let name
= method_names
.add(writer
, method
);
64 let signature
= method_def_signature(writer
.reader
, writer
.reader
.type_def_namespace(def
), method
, generics
);
66 let signature_tokens
= writer
.impl_signature(def
, &signature
);
67 quote
! { fn #name #signature_tokens; }
70 let mut method_names
= MethodNames
::new();
71 method_names
.add_vtable_types(writer
, def
);
73 let method_impls
= writer
.reader
.type_def_methods(def
).map(|method
| {
74 let name
= method_names
.add(writer
, method
);
75 let signature
= method_def_signature(writer
.reader
, writer
.reader
.type_def_namespace(def
), method
, generics
);
76 let vtbl_signature
= writer
.vtbl_signature(def
, generics
, &signature
);
78 let invoke_upcall
= if writer
.reader
.type_def_flags(def
).contains(TypeAttributes
::WindowsRuntime
) { winrt_methods::gen_upcall(writer, &signature, quote! { this.#name }
) } else { com_methods::gen_upcall(writer, &signature, quote! { this.#name }
) };
82 unsafe extern "system" fn #name<#constraints Identity: ::windows_core::IUnknownImpl<Impl = Impl>, Impl: #impl_ident<#generic_names>, const OFFSET: isize> #vtbl_signature {
83 // offset the `this` pointer by `OFFSET` times the size of a pointer and cast it as an IUnknown implementation
84 let this
= (this
as *const *const ()).offset(OFFSET
) as *const Identity
;
85 let this
= (*this
).get_impl();
91 unsafe extern "system" fn #name<Impl: #impl_ident> #vtbl_signature {
92 let this
= (this
as *mut *mut ::core
::ffi
::c_void
) as *const ::windows_core
::ScopedHeap
;
93 let this
= &*((*this
).this
as *const Impl
);
100 let mut methods
= quote
! {}
;
102 match vtables
.last() {
103 Some(Type
::IUnknown
) => methods
.combine("e
! { base__: ::windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(), }
),
104 Some(Type
::IInspectable
) => methods
.combine("e
! { base__: ::windows_core::IInspectable_Vtbl::new::<Identity, #type_ident, OFFSET>(), }
),
105 Some(Type
::TypeDef(def
, generics
)) => {
106 let name
= writer
.type_def_name_imp(*def
, generics
, "_Vtbl");
107 if has_unknown_base
{
108 methods
.combine("e
! { base__: #name::new::<Identity, Impl, OFFSET>(), }
);
110 methods
.combine("e
! { base__: #name::new::<Impl>(), }
);
116 let mut method_names
= MethodNames
::new();
117 method_names
.add_vtable_types(writer
, def
);
119 for method
in writer
.reader
.type_def_methods(def
) {
120 let name
= method_names
.add(writer
, method
);
121 if has_unknown_base
{
122 methods
.combine("e
! { #name: #name::<#generic_names Identity, Impl, OFFSET>, }
);
124 methods
.combine("e
! { #name: #name::<Impl>, }
);
128 if has_unknown_base
{
132 pub trait #impl_ident<#generic_names> : Sized #requires where #constraints {
137 impl<#constraints> #vtbl_ident<#generic_names> {
138 pub const fn new
<Identity
: ::windows_core
::IUnknownImpl
<Impl
= Impl
>, Impl
: #impl_ident<#generic_names>, const OFFSET: isize>() -> #vtbl_ident<#generic_names> {
145 pub fn matches(iid
: &::windows_core
::GUID
) -> bool
{
154 pub trait #impl_ident : Sized #requires {
159 pub const fn new
<Impl
: #impl_ident>() -> #vtbl_ident {
169 struct #implvtbl_ident<T: #impl_ident> (::std::marker::PhantomData<T>);
171 impl<T
: #impl_ident> #implvtbl_ident<T> {
172 const VTABLE
: #vtbl_ident = #vtbl_ident::new::<T>();
176 pub fn new
<'a
, T
: #impl_ident>(this: &'a T) -> ::windows_core::ScopedInterface<'a, Self> {
177 let this
= ::windows_core
::ScopedHeap { vtable: &#implvtbl_ident::<T>::VTABLE as *const _ as *const _, this: this as *const _ as *const _ }
;
178 let this
= ::std
::mem
::ManuallyDrop
::new(::std
::boxed
::Box
::new(this
));
179 unsafe { ::windows_core::ScopedInterface::new(::std::mem::transmute(&this.vtable)) }