windows-bindgen 0.66.0

Code generator for Windows metadata
Documentation
use super::*;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct CppDelegate {
    pub def: TypeDef,
}

impl Ord for CppDelegate {
    fn cmp(&self, other: &Self) -> Ordering {
        (self.def.name(), self.def).cmp(&(other.def.name(), other.def))
    }
}

impl PartialOrd for CppDelegate {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl CppDelegate {
    pub fn type_name(&self) -> TypeName {
        self.def.type_name()
    }

    pub fn write_name(&self, config: &Config) -> TokenStream {
        self.type_name().write(config, &[])
    }

    pub fn method(&self) -> MethodDef {
        self.def
            .methods()
            .find(|method| method.name() == "Invoke")
            .unwrap()
    }

    pub fn write_cfg(&self, config: &Config) -> TokenStream {
        if !config.package {
            return quote! {};
        }

        Cfg::new(&self.dependencies(), config).write(config, false)
    }

    pub fn write(&self, config: &Config) -> TokenStream {
        let type_name = self.def.type_name();
        let name = to_ident(type_name.name());
        let method = self.method();
        let signature = method.signature(type_name.namespace(), &[]);

        let mut params = quote! {};

        for param in &signature.params {
            params.combine(write_param(config, param));
        }

        let return_sig = config.write_return_sig(method, &signature, false);
        let arches = write_arches(self.def);
        let cfg = self.write_cfg(config);

        quote! {
            #arches
            #cfg
            pub type #name = Option<unsafe extern "system" fn(#params) #return_sig>;
        }
    }
}

impl Dependencies for CppDelegate {
    fn combine(&self, dependencies: &mut TypeMap) {
        self.method()
            .signature(self.def.namespace(), &[])
            .combine(dependencies);
    }
}

fn write_param(config: &Config, param: &Param) -> TokenStream {
    let name = param.write_ident();
    let type_name = param.write_name(config);

    if config.sys {
        return quote! { #name: #type_name, };
    }

    if param.is_input() {
        if param.is_copyable() {
            return quote! { #name: #type_name, };
        } else {
            return quote! { #name: windows_core::Ref<#type_name>, };
        }
    }

    let deref = param.deref();

    if deref.is_interface() {
        let type_name = deref.write_name(config);
        quote! { #name: windows_core::OutRef<#type_name>, }
    } else {
        quote! { #name: #type_name, }
    }
}