use super::*;
pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream {
if writer.sys {
gen_sys_interface(def)
} else {
gen_win_interface(writer, def)
}
}
fn gen_sys_interface(def: TypeDef) -> TokenStream {
let name = def.name();
let ident = to_ident(name);
if type_def_is_exclusive(def) {
quote! {}
} else {
quote! {
pub type #ident = *mut ::core::ffi::c_void;
}
}
}
fn gen_win_interface(writer: &Writer, def: TypeDef) -> TokenStream {
let generics = &type_def_generics(def);
let ident = writer.type_def_name(def, generics);
let is_exclusive = type_def_is_exclusive(def);
let phantoms = writer.generic_phantoms(generics);
let constraints = writer.generic_constraints(generics);
let cfg = type_def_cfg(def, &[]);
let doc = writer.cfg_doc(&cfg);
let features = writer.cfg_features(&cfg);
let interfaces = type_interfaces(&Type::TypeDef(def, generics.to_vec()));
let vtables = type_def_vtables(def);
let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown));
let mut tokens = if is_exclusive {
quote! { #[doc(hidden)] }
} else {
quote! { #doc }
};
if has_unknown_base {
tokens.combine("e! {
#features
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #ident(::windows_core::IUnknown, #phantoms) where #constraints;
});
} else {
tokens.combine("e! {
#features
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #ident(::std::ptr::NonNull<::std::ffi::c_void>);
});
}
if !is_exclusive {
let mut methods = quote! {};
let method_names = &mut MethodNames::new();
let virtual_names = &mut MethodNames::new();
if def.flags().contains(TypeAttributes::WindowsRuntime) {
for method in def.methods() {
methods.combine(&winrt_methods::writer(writer, def, generics, InterfaceKind::Default, method, method_names, virtual_names));
}
for interface in &interfaces {
if let Type::TypeDef(def, generics) = &interface.ty {
for method in def.methods() {
methods.combine(&winrt_methods::writer(writer, *def, generics, InterfaceKind::None, method, method_names, virtual_names));
}
}
}
} else {
let mut bases = vtables.len();
for ty in &vtables {
match ty {
Type::IUnknown | Type::IInspectable => {}
Type::TypeDef(def, _) => {
let kind = if def.type_name() == TypeName::IDispatch { InterfaceKind::None } else { InterfaceKind::Default };
for method in def.methods() {
methods.combine(&com_methods::writer(writer, *def, kind, method, method_names, virtual_names, bases));
}
}
rest => unimplemented!("{rest:?}"),
}
bases -= 1;
}
for method in def.methods() {
methods.combine(&com_methods::writer(writer, def, InterfaceKind::Default, method, method_names, virtual_names, 0));
}
}
tokens.combine("e! {
#features
impl<#constraints> #ident {
#methods
}
});
if !vtables.is_empty() && generics.is_empty() {
let mut hierarchy = format!("::windows_core::imp::interface_hierarchy!({ident}");
let mut hierarchy_cfg = cfg.clone();
for ty in &vtables {
let into = writer.type_name(ty);
write!(&mut hierarchy, ", {into}").unwrap();
hierarchy_cfg = hierarchy_cfg.union(&type_cfg(ty));
}
hierarchy.push_str(");");
tokens.combine(&writer.cfg_features(&hierarchy_cfg));
tokens.push_str(&hierarchy);
} else {
for ty in &vtables {
let into = writer.type_name(ty);
let cfg = writer.cfg_features(&cfg.union(&type_cfg(ty)));
tokens.combine("e! {
#cfg
impl<#constraints> ::windows_core::CanInto<#into> for #ident {}
});
}
}
if def.flags().contains(TypeAttributes::WindowsRuntime) {
for interface in &interfaces {
let into = writer.type_name(&interface.ty);
let cfg = writer.cfg_features(&cfg.union(&type_cfg(&interface.ty)));
tokens.combine("e! {
#cfg
impl<#constraints> ::windows_core::CanTryInto<#into> for #ident {}
});
}
}
tokens.combine(&writer.interface_winrt_trait(def, generics, &ident, &constraints, &phantoms, &features));
tokens.combine(&writer.async_get(def, generics, &ident, &constraints, &phantoms, &features));
tokens.combine(&iterators::writer(writer, def, generics, &ident, &constraints, &phantoms, &cfg));
tokens.combine(&writer.agile(def, &ident, &constraints, &features));
}
tokens.combine(&writer.interface_trait(def, generics, &ident, &constraints, &features, has_unknown_base));
tokens.combine(&writer.interface_vtbl(def, generics, &ident, &constraints, &features));
tokens
}