Skip to content

Commit

Permalink
bindgen
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Oct 17, 2023
1 parent 1a81f41 commit 8c502ce
Showing 1 changed file with 59 additions and 59 deletions.
118 changes: 59 additions & 59 deletions crates/libs/bindgen/src/rust/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::*;

#[derive(Clone)]
pub struct Writer<'a> {
pub reader: &'a Reader<'a>,
pub reader: &'a Reader,
pub filter: &'a metadata::Filter<'a>,
pub output: &'a str,
pub namespace: &'a str,
Expand Down Expand Up @@ -36,7 +36,7 @@ impl<'a> Writer<'a> {
self.type_def_name_imp(def, generics, "_Vtbl")
}
pub fn type_def_name_imp(&self, def: TypeDef, generics: &[Type], suffix: &str) -> TokenStream {
let type_name = self.reader.type_def_type_name(def);
let type_name = def.type_name();

if type_name.namespace.is_empty() {
to_ident(&self.scoped_name(def))
Expand Down Expand Up @@ -73,7 +73,7 @@ impl<'a> Writer<'a> {

if ty.is_generic() {
quote! { <#kind as ::windows_core::Type<#kind>>::Default }
} else if type_is_nullable(self.reader, ty) && !self.sys {
} else if type_is_nullable(ty) && !self.sys {
quote! { ::core::option::Option<#kind> }
} else {
kind
Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'a> Writer<'a> {
let len = Literal::usize_unsuffixed(*len);
quote! { [#name; #len] }
}
Type::GenericParam(generic) => self.reader.generic_param_name(*generic).into(),
Type::GenericParam(generic) => generic.name().into(),
Type::TypeDef(def, generics) => self.type_def_name(*def, generics),
Type::MutPtr(ty, pointers) => {
let pointers = mut_ptrs(*pointers);
Expand Down Expand Up @@ -192,10 +192,10 @@ impl<'a> Writer<'a> {
quote! { [#name; #len] }
}
Type::GenericParam(generic) => {
let name = to_ident(self.reader.generic_param_name(*generic));
let name = to_ident(generic.name());
quote! { ::windows_core::AbiType<#name> }
}
Type::TypeDef(def, _) => match self.reader.type_def_kind(*def) {
Type::TypeDef(def, _) => match def.kind() {
TypeKind::Enum => self.type_def_name(*def, &[]),
TypeKind::Struct => {
let tokens = self.type_def_name(*def, &[]);
Expand All @@ -206,7 +206,7 @@ impl<'a> Writer<'a> {
}
}
TypeKind::Delegate => {
if self.reader.type_def_flags(*def).contains(TypeAttributes::WindowsRuntime) {
if def.flags().contains(TypeAttributes::WindowsRuntime) {
quote! { *mut ::core::ffi::c_void }
} else {
self.type_def_name(*def, &[])
Expand Down Expand Up @@ -480,14 +480,14 @@ impl<'a> Writer<'a> {
}
}
fn scoped_name(&self, def: TypeDef) -> String {
if let Some(enclosing_type) = self.reader.type_def_enclosing_type(def) {
if let Some(enclosing_type) = def.enclosing_type() {
for (index, nested_type) in self.reader.nested_types(enclosing_type).enumerate() {
if self.reader.type_def_name(nested_type) == self.reader.type_def_name(def) {
if nested_type.name() == def.name() {
return format!("{}_{index}", &self.scoped_name(enclosing_type));
}
}
}
self.reader.type_def_name(def).to_string()
def.name().to_string()
}
pub fn value(&self, value: &Value) -> TokenStream {
match value {
Expand Down Expand Up @@ -536,12 +536,12 @@ impl<'a> Writer<'a> {
}
}

pub fn guid(&self, value: &GUID) -> TokenStream {
pub fn guid(&self, value: &Guid) -> TokenStream {
let guid = self.type_name(&Type::GUID);
format!("{}::from_u128(0x{:08x?}_{:04x?}_{:04x?}_{:02x?}{:02x?}_{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?})", guid.into_string(), value.0, value.1, value.2, value.3, value.4, value.5, value.6, value.7, value.8, value.9, value.10).into()
}
pub fn agile(&self, def: TypeDef, ident: &TokenStream, constraints: &TokenStream, features: &TokenStream) -> TokenStream {
if type_def_is_agile(self.reader, def) {
if type_def_is_agile(def) {
quote! {
#features
unsafe impl<#constraints> ::core::marker::Send for #ident {}
Expand All @@ -553,13 +553,13 @@ impl<'a> Writer<'a> {
}
}
pub fn async_get(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream {
let mut kind = type_def_async_kind(self.reader, def);
let mut kind = type_def_async_kind(def);
let mut async_generics = generics.to_vec();

if kind == AsyncKind::None {
for interface in type_def_interfaces(self.reader, def, generics) {
for interface in type_def_interfaces(def, generics) {
if let Type::TypeDef(interface_def, interface_generics) = &interface {
kind = type_def_async_kind(self.reader, *interface_def);
kind = type_def_async_kind(*interface_def);
if kind != AsyncKind::None {
async_generics = interface_generics.to_vec();
break;
Expand Down Expand Up @@ -626,14 +626,14 @@ impl<'a> Writer<'a> {
}
}
pub fn interface_winrt_trait(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream {
if self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) {
let type_signature = if self.reader.type_def_kind(def) == TypeKind::Class {
if def.flags().contains(TypeAttributes::WindowsRuntime) {
let type_signature = if def.kind() == TypeKind::Class {
let type_signature = Literal::byte_string(type_def_signature(self.reader, def, generics).as_bytes());
quote! { ::windows_core::imp::ConstBuffer::from_slice(#type_signature) }
} else {
let signature = Literal::byte_string(
// TODO: workaround for riddle winmd generation (no attribute support)
if let Some(guid) = type_def_guid(self.reader, def) { format!("{{{:#?}}}", guid) } else { "TODO".to_string() }.as_bytes(),
if let Some(guid) = type_def_guid(def) { format!("{{{:#?}}}", guid) } else { "TODO".to_string() }.as_bytes(),
);

if generics.is_empty() {
Expand Down Expand Up @@ -679,9 +679,9 @@ impl<'a> Writer<'a> {
}
}
pub fn runtime_name_trait(&self, def: TypeDef, _generics: &[Type], name: &TokenStream, constraints: &TokenStream, features: &TokenStream) -> TokenStream {
if self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) {
if def.flags().contains(TypeAttributes::WindowsRuntime) {
// TODO: this needs to use a ConstBuffer-like facility to accomodate generics
let runtime_name = format!("{}", self.reader.type_def_type_name(def));
let runtime_name = format!("{}", def.type_name());

quote! {
#features
Expand All @@ -698,7 +698,7 @@ impl<'a> Writer<'a> {
}

pub fn interface_trait(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, features: &TokenStream, has_unknown_base: bool) -> TokenStream {
if let Some(default) = type_def_default_interface(self.reader, def) {
if let Some(default) = type_def_default_interface(def) {
let default_name = self.type_name(&default);
let vtbl = self.type_vtbl_name(&default);
quote! {
Expand All @@ -714,7 +714,7 @@ impl<'a> Writer<'a> {
} else {
let vtbl = self.type_def_vtbl_name(def, generics);
let guid = if generics.is_empty() {
match type_def_guid(self.reader, def) {
match type_def_guid(def) {
Some(guid) => self.guid(&guid),
None => {
quote! {
Expand Down Expand Up @@ -751,10 +751,10 @@ impl<'a> Writer<'a> {
let vtbl = self.type_def_vtbl_name(def, generics);
let mut methods = quote! {};
let mut method_names = MethodNames::new();
method_names.add_vtable_types(self, def);
method_names.add_vtable_types(def);
let phantoms = self.generic_named_phantoms(generics);

match type_def_vtables(self.reader, def).last() {
match type_def_vtables(def).last() {
Some(Type::IUnknown) => methods.combine(&quote! { pub base__: ::windows_core::IUnknown_Vtbl, }),
Some(Type::IInspectable) => methods.combine(&quote! { pub base__: ::windows_core::IInspectable_Vtbl, }),
Some(Type::TypeDef(def, _)) => {
Expand All @@ -764,15 +764,15 @@ impl<'a> Writer<'a> {
_ => {}
}

for method in self.reader.type_def_methods(def) {
if self.reader.method_def_name(method) == ".ctor" {
for method in def.methods() {
if method.name() == ".ctor" {
continue;
}
let name = method_names.add(self, method);
let signature = method_def_signature(self.reader, self.reader.type_def_namespace(def), method, generics);
let name = method_names.add(method);
let signature = method_def_signature(self.reader, def.namespace(), method, generics);
let mut cfg = signature_cfg(self.reader, method);
let signature = self.vtbl_signature(def, generics, &signature);
cfg.add_feature(self.reader.type_def_namespace(def));
cfg.add_feature(def.namespace());
let cfg_all = self.cfg_features(&cfg);
let cfg_not = self.cfg_not_features(&cfg);

Expand All @@ -799,7 +799,7 @@ impl<'a> Writer<'a> {
}
}
pub fn vtbl_signature(&self, def: TypeDef, _generics: &[Type], signature: &Signature) -> TokenStream {
let is_winrt = self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime);
let is_winrt = def.flags().contains(TypeAttributes::WindowsRuntime);

let crate_name = self.crate_name();

Expand All @@ -814,7 +814,7 @@ impl<'a> Writer<'a> {
let tokens = self.type_abi_name(&signature.return_type);
(quote! { result__: *mut #tokens }, quote! { -> #crate_name HRESULT }, quote! {})
}
_ if type_is_struct(self.reader, &signature.return_type) => {
_ if type_is_struct(&signature.return_type) => {
let tokens = self.type_abi_name(&signature.return_type);
(quote! {}, quote! {}, quote! { result__: *mut #tokens, })
}
Expand All @@ -828,9 +828,9 @@ impl<'a> Writer<'a> {
let name = self.param_name(p.def);
if is_winrt {
let abi = self.type_abi_name(&p.ty);
let abi_size_name: TokenStream = format!("{}_array_size", self.reader.param_name(p.def)).into();
let abi_size_name: TokenStream = format!("{}_array_size", p.def.name()).into();

if self.reader.param_flags(p.def).contains(ParamAttributes::In) {
if p.def.flags().contains(ParamAttributes::In) {
if p.ty.is_winrt_array() {
quote! { #abi_size_name: u32, #name: *const #abi, }
} else if p.ty.is_const_ref() {
Expand Down Expand Up @@ -864,11 +864,11 @@ impl<'a> Writer<'a> {
pub fn param_name(&self, param: Param) -> TokenStream {
// In Rust, function parameters cannot be named the same as structs. This avoids some collisions that occur in the win32 metadata.
// See Icmp6SendEcho2 for an example.
to_ident(&self.reader.param_name(param).to_lowercase())
to_ident(&param.name().to_lowercase())
}
pub fn return_sig(&self, signature: &Signature) -> TokenStream {
match &signature.return_type {
Type::Void if self.reader.has_attribute(signature.def, "DoesNotReturnAttribute") => " -> !".into(),
Type::Void if signature.def.has_attribute("DoesNotReturnAttribute") => " -> !".into(),
Type::Void => " -> ()".into(),
_ => {
let tokens = self.type_default_name(&signature.return_type);
Expand All @@ -895,7 +895,7 @@ impl<'a> Writer<'a> {
}
_ => {
let name = self.param_name(param.def);
let flags = self.reader.param_flags(param.def);
let flags = param.def.flags();
match param.kind {
SignatureParamKind::ArrayFixed(_) | SignatureParamKind::ArrayRelativeLen(_) | SignatureParamKind::ArrayRelativeByteLen(_) => {
let map = if flags.contains(ParamAttributes::Optional) {
Expand All @@ -907,7 +907,7 @@ impl<'a> Writer<'a> {
}
SignatureParamKind::ArrayRelativePtr(relative) => {
let name = self.param_name(params[relative].def);
let flags = self.reader.param_flags(params[relative].def);
let flags = params[relative].def.flags();
if flags.contains(ParamAttributes::Optional) {
quote! { #name.as_deref().map_or(0, |slice|slice.len() as _), }
} else {
Expand Down Expand Up @@ -972,12 +972,12 @@ impl<'a> Writer<'a> {
let ty = param.ty.deref();
let ty = self.type_default_name(&ty);
let len = Literal::u32_unsuffixed(fixed as u32);
let ty = if self.reader.param_flags(param.def).contains(ParamAttributes::Out) {
let ty = if param.def.flags().contains(ParamAttributes::Out) {
quote! { &mut [#ty; #len] }
} else {
quote! { &[#ty; #len] }
};
if self.reader.param_flags(param.def).contains(ParamAttributes::Optional) {
if param.def.flags().contains(ParamAttributes::Optional) {
tokens.combine(&quote! { #name: ::core::option::Option<#ty>, });
} else {
tokens.combine(&quote! { #name: #ty, });
Expand All @@ -986,24 +986,24 @@ impl<'a> Writer<'a> {
SignatureParamKind::ArrayRelativeLen(_) => {
let ty = param.ty.deref();
let ty = self.type_default_name(&ty);
let ty = if self.reader.param_flags(param.def).contains(ParamAttributes::Out) {
let ty = if param.def.flags().contains(ParamAttributes::Out) {
quote! { &mut [#ty] }
} else {
quote! { &[#ty] }
};
if self.reader.param_flags(param.def).contains(ParamAttributes::Optional) {
if param.def.flags().contains(ParamAttributes::Optional) {
tokens.combine(&quote! { #name: ::core::option::Option<#ty>, });
} else {
tokens.combine(&quote! { #name: #ty, });
}
}
SignatureParamKind::ArrayRelativeByteLen(_) => {
let ty = if self.reader.param_flags(param.def).contains(ParamAttributes::Out) {
let ty = if param.def.flags().contains(ParamAttributes::Out) {
quote! { &mut [u8] }
} else {
quote! { &[u8] }
};
if self.reader.param_flags(param.def).contains(ParamAttributes::Optional) {
if param.def.flags().contains(ParamAttributes::Optional) {
tokens.combine(&quote! { #name: ::core::option::Option<#ty>, });
} else {
tokens.combine(&quote! { #name: #ty, });
Expand Down Expand Up @@ -1034,8 +1034,8 @@ impl<'a> Writer<'a> {
}

pub fn impl_signature(&self, def: TypeDef, signature: &Signature) -> TokenStream {
if self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) {
let is_delegate = self.reader.type_def_kind(def) == TypeKind::Delegate;
if def.flags().contains(TypeAttributes::WindowsRuntime) {
let is_delegate = def.kind() == TypeKind::Delegate;
let params = signature.params.iter().map(|p| self.winrt_produce_type(p, !is_delegate));

let return_type = match &signature.return_type {
Expand All @@ -1059,7 +1059,7 @@ impl<'a> Writer<'a> {

quote! { (#this #(#params),*) -> ::windows_core::Result<#return_type> }
} else {
let signature_kind = signature_kind(self.reader, signature);
let signature_kind = signature_kind(signature);
let mut params = quote! {};

if signature_kind == SignatureKind::ResultValue {
Expand Down Expand Up @@ -1090,12 +1090,12 @@ impl<'a> Writer<'a> {
fn winrt_produce_type(&self, param: &SignatureParam, include_param_names: bool) -> TokenStream {
let default_type = self.type_default_name(&param.ty);

let sig = if self.reader.param_flags(param.def).contains(ParamAttributes::In) {
let sig = if param.def.flags().contains(ParamAttributes::In) {
if param.ty.is_winrt_array() {
quote! { &[#default_type] }
} else if type_is_primitive(self.reader, &param.ty) {
} else if type_is_primitive(&param.ty) {
quote! { #default_type }
} else if type_is_nullable(self.reader, &param.ty) {
} else if type_is_nullable(&param.ty) {
let type_name = self.type_name(&param.ty);
quote! { ::core::option::Option<&#type_name> }
} else {
Expand All @@ -1121,10 +1121,10 @@ impl<'a> Writer<'a> {
let name = self.param_name(param.def);
let kind = self.type_default_name(&param.ty);

if self.reader.param_flags(param.def).contains(ParamAttributes::In) {
if type_is_primitive(self.reader, &param.ty) {
if param.def.flags().contains(ParamAttributes::In) {
if type_is_primitive(&param.ty) {
quote! { #name: #kind, }
} else if type_is_nullable(self.reader, &param.ty) {
} else if type_is_nullable(&param.ty) {
let kind = self.type_name(&param.ty);
quote! { #name: ::core::option::Option<&#kind>, }
} else {
Expand Down Expand Up @@ -1181,8 +1181,8 @@ fn gen_const_ptrs(pointers: usize) -> TokenStream {
"*const ".repeat(pointers).into()
}

fn type_def_async_kind(reader: &Reader, row: TypeDef) -> AsyncKind {
match reader.type_def_type_name(row) {
fn type_def_async_kind(row: TypeDef) -> AsyncKind {
match row.type_name() {
TypeName::IAsyncAction => AsyncKind::Action,
TypeName::IAsyncActionWithProgress => AsyncKind::ActionWithProgress,
TypeName::IAsyncOperation => AsyncKind::Operation,
Expand All @@ -1191,12 +1191,12 @@ fn type_def_async_kind(reader: &Reader, row: TypeDef) -> AsyncKind {
}
}

fn type_def_is_agile(reader: &Reader, row: TypeDef) -> bool {
for attribute in reader.attributes(row) {
match reader.attribute_name(attribute) {
fn type_def_is_agile(row: TypeDef) -> bool {
for attribute in row.attributes() {
match attribute.name() {
"AgileAttribute" => return true,
"MarshalingBehaviorAttribute" => {
if let Some((_, Value::EnumDef(_, value))) = reader.attribute_args(attribute).get(0) {
if let Some((_, Value::EnumDef(_, value))) = attribute.args().get(0) {
if let Value::I32(2) = **value {
return true;
}
Expand All @@ -1205,7 +1205,7 @@ fn type_def_is_agile(reader: &Reader, row: TypeDef) -> bool {
_ => {}
}
}
matches!(reader.type_def_type_name(row), TypeName::IAsyncAction | TypeName::IAsyncActionWithProgress | TypeName::IAsyncOperation | TypeName::IAsyncOperationWithProgress)
matches!(row.type_name(), TypeName::IAsyncAction | TypeName::IAsyncActionWithProgress | TypeName::IAsyncOperation | TypeName::IAsyncOperationWithProgress)
}

#[cfg(test)]
Expand Down

0 comments on commit 8c502ce

Please sign in to comment.