com_macros_support/class/
class_factory.rs

1use super::Class;
2use proc_macro2::TokenStream;
3use quote::quote;
4
5pub fn generate(class: &Class) -> TokenStream {
6    if !class.has_class_factory {
7        return TokenStream::new();
8    }
9
10    let class_factory_ident = crate::utils::class_factory_ident(&class.name);
11    let class_name = &class.name;
12    let user_fields = class.fields.iter().map(|f| {
13        let ty = &f.ty;
14        quote! { <#ty as ::core::default::Default>::default() }
15    });
16    quote! {
17        ::com::class! {
18            #[no_class_factory]
19            pub class #class_factory_ident: ::com::interfaces::IClassFactory {}
20
21            impl ::com::interfaces::IClassFactory for #class_factory_ident {
22                unsafe fn CreateInstance(
23                    &self,
24                    aggr: *mut ::core::ptr::NonNull<<::com::interfaces::IUnknown as ::com::Interface>::VTable>,
25                    riid: *const ::com::sys::IID,
26                    ppv: *mut *mut ::core::ffi::c_void,
27                ) -> ::com::sys::HRESULT {
28                    assert!(!riid.is_null(), "iid passed to CreateInstance was null");
29                    if !aggr.is_null() {
30                        return ::com::sys::CLASS_E_NOAGGREGATION;
31                    }
32
33                    let instance = #class_name::allocate(#(#user_fields),*);
34                    instance.QueryInterface(riid, ppv)
35                }
36
37                unsafe fn LockServer(&self, _increment: com::sys::BOOL) -> com::sys::HRESULT {
38                    ::com::sys::S_OK
39                }
40            }
41        }
42    }
43}