windows-bindgen 0.66.0

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

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

impl Struct {
    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 write(&self, config: &Config) -> TokenStream {
        let name = to_ident(self.def.name());

        let fields: Vec<_> = self
            .def
            .fields()
            .map(|field| (field.name(), field.ty(None)))
            .collect();

        let is_copyable = fields.iter().all(|(_, ty)| ty.is_copyable());

        let mut derive = DeriveWriter::new(config, self.type_name());
        derive.extend(["Clone"]);

        if is_copyable {
            derive.extend(["Copy"]);
        }

        if !config.sys {
            derive.extend(["Default", "Debug", "PartialEq"]);
        }

        let fields = fields.iter().map(|(name, ty)| {
            let name = to_ident(name);
            let ty = ty.write_default(config);
            quote! { pub #name: #ty, }
        });

        let win_traits = if config.sys {
            quote! {}
        } else {
            let type_kind = if is_copyable {
                quote! { CopyType }
            } else {
                quote! { CloneType }
            };

            let signature = Literal::byte_string(&self.runtime_signature());

            quote! {
                impl windows_core::TypeKind for #name {
                    type TypeKind = windows_core::#type_kind;
                }
                impl windows_core::RuntimeType for #name {
                    const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice(#signature);
                }
            }
        };

        quote! {
            #[repr(C)]
            #derive
            pub struct #name {
                #(#fields)*
            }
            #win_traits
        }
    }

    pub fn runtime_signature(&self) -> String {
        let mut signature = format!("struct({}", self.def.type_name());
        for field in self.def.fields() {
            signature.push(';');
            signature.push_str(&field.ty(None).runtime_signature());
        }
        signature.push(')');
        signature
    }

    pub fn is_copyable(&self) -> bool {
        self.def.fields().all(|field| field.ty(None).is_copyable())
    }

    pub fn size(&self) -> usize {
        let mut sum = 0;
        for field in self.def.fields() {
            let ty = field.ty(None);
            let size = ty.size();
            let align = ty.align();
            sum = (sum + (align - 1)) & !(align - 1);
            sum += size;
        }
        sum
    }

    pub fn align(&self) -> usize {
        self.def
            .fields()
            .map(|field| field.ty(None).align())
            .max()
            .unwrap_or(1)
    }
}

impl Dependencies for Struct {
    fn combine(&self, dependencies: &mut TypeMap) {
        for field in self.def.fields() {
            field.ty(None).combine(dependencies);
        }
    }
}