diff options
Diffstat (limited to 'vendor/windows-bindgen/src/classes.rs')
-rw-r--r-- | vendor/windows-bindgen/src/classes.rs | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/vendor/windows-bindgen/src/classes.rs b/vendor/windows-bindgen/src/classes.rs new file mode 100644 index 000000000..3cdf50006 --- /dev/null +++ b/vendor/windows-bindgen/src/classes.rs @@ -0,0 +1,215 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + if gen.reader.type_def_has_default_interface(def) { + let name = to_ident(gen.reader.type_def_name(def)); + quote! { + pub type #name = *mut ::core::ffi::c_void; + } + } else { + quote! {} + } + } else { + gen_class(gen, def) + } +} + +fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.reader.type_def_extends(def) == TypeName::Attribute { + return TokenStream::new(); + } + + let name = to_ident(gen.reader.type_def_name(def)); + let interfaces = gen + .reader + .type_interfaces(&Type::TypeDef((def, Vec::new()))); + let mut methods = quote! {}; + let mut method_names = MethodNames::new(); + + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + for interface in &interfaces { + if let Type::TypeDef((def, generics)) = &interface.ty { + let mut virtual_names = MethodNames::new(); + + for method in gen.reader.type_def_methods(*def) { + methods.combine(&winrt_methods::gen( + gen, + *def, + generics, + interface.kind, + method, + &mut method_names, + &mut virtual_names, + )); + } + } + } + + let factories = interfaces.iter().filter_map(|interface| match interface.kind { + InterfaceKind::Static => { + if let Type::TypeDef((def, generics)) = &interface.ty { + if gen.reader.type_def_methods(*def).next().is_some() { + let interface_type = gen.type_name(&interface.ty); + let features = gen.cfg_features(&gen.reader.type_def_cfg(*def, generics)); + + let hidden = if gen.doc { + quote! { #[doc(hidden)] } + } else { + quote! {} + }; + + return Some(quote! { + #hidden + #features + pub fn #interface_type<R, F: FnOnce(&#interface_type) -> ::windows::core::Result<R>>( + callback: F, + ) -> ::windows::core::Result<R> { + static SHARED: ::windows::imp::FactoryCache<#name, #interface_type> = + ::windows::imp::FactoryCache::new(); + SHARED.call(callback) + } + }); + } + } + None + } + _ => None, + }); + + if gen.reader.type_def_has_default_interface(def) { + let new = if gen.reader.type_def_has_default_constructor(def) { + quote! { + pub fn new() -> ::windows::core::Result<Self> { + Self::IActivationFactory(|f| f.ActivateInstance::<Self>()) + } + fn IActivationFactory<R, F: FnOnce(&::windows::imp::IGenericFactory) -> ::windows::core::Result<R>>( + callback: F, + ) -> ::windows::core::Result<R> { + static SHARED: ::windows::imp::FactoryCache<#name, ::windows::imp::IGenericFactory> = + ::windows::imp::FactoryCache::new(); + SHARED.call(callback) + } + } + } else { + quote! {} + }; + + let mut tokens = quote! { + #doc + #features + #[repr(transparent)] + pub struct #name(::windows::core::IUnknown); + #features + impl #name { + #new + #methods + #(#factories)* + } + }; + + tokens.combine(&gen.interface_core_traits( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&gen.interface_winrt_trait( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&gen.interface_trait(def, &[], &name, &TokenStream::new(), &features, true)); + tokens.combine(&gen.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens.combine(&gen.async_get( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&iterators::gen( + gen, + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &cfg, + )); + tokens.combine(&gen_conversions(gen, def, &name, &interfaces, &cfg)); + tokens.combine(&gen.agile(def, &name, &TokenStream::new(), &features)); + tokens + } else { + let mut tokens = quote! { + #doc + #features + pub struct #name; + #features + impl #name { + #methods + #(#factories)* + } + }; + + tokens.combine(&gen.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens + } +} + +fn gen_conversions( + gen: &Gen, + def: TypeDef, + name: &TokenStream, + interfaces: &[Interface], + cfg: &Cfg, +) -> TokenStream { + let features = gen.cfg_features(cfg); + let mut tokens = quote! { + #features + ::windows::imp::interface_hierarchy!(#name, ::windows::core::IUnknown, ::windows::core::IInspectable); + }; + + for interface in interfaces { + if gen.reader.type_is_exclusive(&interface.ty) { + continue; + } + + if interface.kind != InterfaceKind::Default + && interface.kind != InterfaceKind::None + && interface.kind != InterfaceKind::Base + { + continue; + } + + let into = gen.type_name(&interface.ty); + // TODO: simplify - maybe provide + operator? + let features = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty))); + + tokens.combine("e! { + #features + impl ::windows::core::CanTryInto<#into> for #name {} + }); + } + + for def in gen.reader.type_def_bases(def) { + let into = gen.type_def_name(def, &[]); + let features = gen.cfg_features(&cfg.union(&gen.reader.type_def_cfg(def, &[]))); + + tokens.combine("e! { + #features + impl ::windows::core::CanTryInto<#into> for #name {} + }); + } + + tokens +} |