diff --git a/crates/libs/bindgen/src/lib.rs b/crates/libs/bindgen/src/lib.rs index 713a1b12df..4082ca04bc 100644 --- a/crates/libs/bindgen/src/lib.rs +++ b/crates/libs/bindgen/src/lib.rs @@ -12,6 +12,7 @@ mod filter; mod guid; mod io; mod libraries; +mod param; mod references; mod signature; mod tables; @@ -30,6 +31,7 @@ use filter::*; use guid::*; use io::*; pub use libraries::*; +use param::*; use references::*; use signature::*; use std::cmp::Ordering; diff --git a/crates/libs/bindgen/src/param.rs b/crates/libs/bindgen/src/param.rs new file mode 100644 index 0000000000..7b28d04eba --- /dev/null +++ b/crates/libs/bindgen/src/param.rs @@ -0,0 +1,69 @@ +use super::*; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Param { + pub def: MethodParam, + pub ty: Type, +} + +impl std::ops::Deref for Param { + type Target = Type; + + fn deref(&self) -> &Self::Target { + &self.ty + } +} + +impl Param { + pub fn is_convertible(&self) -> bool { + self.is_input() && self.ty.is_convertible() + } + + pub fn is_input(&self) -> bool { + !self.def.flags().contains(ParamAttributes::Out) + } + + pub fn is_optional(&self) -> bool { + self.def.flags().contains(ParamAttributes::Optional) + || self.def.has_attribute("ReservedAttribute") + } + + pub fn is_retval(&self) -> bool { + if !self.ty.is_pointer() { + return false; + } + + if self.ty.is_void() { + return false; + } + + let flags = self.def.flags(); + + if flags.contains(ParamAttributes::In) + || !flags.contains(ParamAttributes::Out) + || flags.contains(ParamAttributes::Optional) + { + return false; + } + + for attribute in self.def.attributes() { + if matches!( + attribute.name(), + "NativeArrayInfoAttribute" | "MemorySizeAttribute" + ) { + return false; + } + } + + // If it's bigger than 128 bits, best to pass as a reference. + if self.ty.deref().size() > 16 { + return false; + } + + true + } + + pub fn write_ident(&self) -> TokenStream { + to_ident(&self.def.name().to_lowercase()) + } +} diff --git a/crates/libs/bindgen/src/signature.rs b/crates/libs/bindgen/src/signature.rs index d8980cd473..95254efd7d 100644 --- a/crates/libs/bindgen/src/signature.rs +++ b/crates/libs/bindgen/src/signature.rs @@ -3,27 +3,44 @@ use super::*; #[derive(Clone, Debug, PartialEq, Eq)] pub struct Signature { pub call_flags: MethodCallAttributes, - pub return_type: (Type, Option), - pub params: Vec<(Type, Param)>, + pub return_type: Type, + pub params: Vec, } impl Signature { pub fn size(&self) -> usize { self.params .iter() - .fold(0, |sum, param| sum + std::cmp::max(4, param.0.size())) + .fold(0, |sum, param| sum + std::cmp::max(4, param.size())) } pub fn dependencies(&self, dependencies: &mut TypeMap) { - self.return_type.0.dependencies(dependencies); - self.params - .iter() - .for_each(|(ty, _)| ty.dependencies(dependencies)); + self.types().for_each(|ty| ty.dependencies(dependencies)); } pub fn types(&self) -> impl Iterator + '_ { - std::iter::once(&self.return_type.0) - .chain(self.params.iter().map(|(ty, _)| ty)) + std::iter::once(&self.return_type) + .chain(self.params.iter().map(|param| ¶m.ty)) .map(|ty| ty.decay()) } + + pub fn is_retval(&self) -> bool { + // First we check whether there's an explicit retval parameter. + if let Some(param) = self.params.last() { + if param.def.has_attribute("RetValAttribute") { + return true; + } + } + + // Otherwise we check for heuristically for additional candidates. + if let Some(param) = self.params.last() { + if param.is_retval() { + return self.params[..self.params.len() - 1] + .iter() + .all(|param| param.is_input()); + } + } + + false + } } diff --git a/crates/libs/bindgen/src/tables/method_def.rs b/crates/libs/bindgen/src/tables/method_def.rs index 6098bf253e..e58a2ec652 100644 --- a/crates/libs/bindgen/src/tables/method_def.rs +++ b/crates/libs/bindgen/src/tables/method_def.rs @@ -15,7 +15,7 @@ impl MethodDef { self.str(3) } - pub fn params(&self) -> RowIterator { + pub fn params(&self) -> RowIterator { self.list(5) } @@ -35,7 +35,6 @@ impl MethodDef { let call_flags = MethodCallAttributes(blob.read_usize() as u8); let _param_count = blob.read_usize(); let mut return_type = Type::from_blob(&mut blob, None, generics); - let mut return_param = None; let mut params = vec![]; @@ -44,21 +43,18 @@ impl MethodDef { if param.has_attribute("ConstAttribute") { return_type = return_type.to_const_type(); } - - return_param = Some(param); } else { let param_is_const = param.has_attribute("ConstAttribute"); - let param_is_output = param.flags().contains(ParamAttributes::Out); + let param_is_input = !param.flags().contains(ParamAttributes::Out); let mut ty = Type::from_blob(&mut blob, None, generics); - if param_is_const || !param_is_output { + if param_is_const || param_is_input { ty = ty.to_const_type(); } - if !param_is_output { + + if param_is_input { ty = ty.to_const_ptr(); - } - if !param_is_output { if let Some(attribute) = param.find_attribute("AssociatedEnumAttribute") { if let Some((_, Value::Str(name))) = attribute.args().first() { let overload = param.reader().unwrap_full_name(namespace, name); @@ -68,13 +64,13 @@ impl MethodDef { } } - params.push((ty, param)); + params.push(Param { def: param, ty }); } } Signature { call_flags, - return_type: (return_type, return_param), + return_type, params, } } diff --git a/crates/libs/bindgen/src/tables/param.rs b/crates/libs/bindgen/src/tables/method_param.rs similarity index 73% rename from crates/libs/bindgen/src/tables/param.rs rename to crates/libs/bindgen/src/tables/method_param.rs index 9e88becfe9..f966d5fe00 100644 --- a/crates/libs/bindgen/src/tables/param.rs +++ b/crates/libs/bindgen/src/tables/method_param.rs @@ -1,12 +1,12 @@ use super::*; -impl std::fmt::Debug for Param { +impl std::fmt::Debug for MethodParam { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("Param").field(&self.name()).finish() + f.debug_tuple("MethodParam").field(&self.name()).finish() } } -impl Param { +impl MethodParam { pub fn flags(&self) -> ParamAttributes { ParamAttributes(self.usize(0) as u16) } diff --git a/crates/libs/bindgen/src/tables/mod.rs b/crates/libs/bindgen/src/tables/mod.rs index ea49c1417c..55e08d7f63 100644 --- a/crates/libs/bindgen/src/tables/mod.rs +++ b/crates/libs/bindgen/src/tables/mod.rs @@ -9,9 +9,9 @@ mod impl_map; mod interface_impl; mod member_ref; mod method_def; +mod method_param; mod module_ref; mod nested_class; -mod param; mod type_def; mod type_ref; mod type_spec; @@ -46,7 +46,7 @@ tables! { (MethodDef, 6) (ModuleRef, 12) (NestedClass, 13) - (Param, 7) + (MethodParam, 7) (TypeDef, 8) (TypeRef, 9) (TypeSpec, 10) diff --git a/crates/libs/bindgen/src/tables/type_def.rs b/crates/libs/bindgen/src/tables/type_def.rs index f5bb1b59f3..7072208746 100644 --- a/crates/libs/bindgen/src/tables/type_def.rs +++ b/crates/libs/bindgen/src/tables/type_def.rs @@ -44,7 +44,7 @@ impl TypeDef { pub fn generics(&self) -> Vec { self.file() .equal_range(2, TypeOrMethodDef::TypeDef(*self).encode()) - .map(|generic: GenericParam| Type::Param(generic.name())) + .map(|generic: GenericParam| Type::Generic(generic.name())) .collect() } diff --git a/crates/libs/bindgen/src/types/cpp_delegate.rs b/crates/libs/bindgen/src/types/cpp_delegate.rs index 8b79919130..b572bf6c6e 100644 --- a/crates/libs/bindgen/src/types/cpp_delegate.rs +++ b/crates/libs/bindgen/src/types/cpp_delegate.rs @@ -51,8 +51,8 @@ impl CppDelegate { let mut params = quote! {}; - for (ty, param) in &signature.params { - params.combine(write_param(writer, ty, *param)); + for param in &signature.params { + params.combine(write_param(writer, param)); } let return_sig = writer.write_return_sig(method, &signature, false); @@ -73,24 +73,28 @@ impl CppDelegate { } } -fn write_param(writer: &Writer, ty: &Type, param: Param) -> TokenStream { - let name = to_ident(¶m.name().to_lowercase()); - let type_name = ty.write_name(writer); +fn write_param(writer: &Writer, param: &Param) -> TokenStream { + let name = param.write_ident(); + let type_name = param.write_name(writer); if writer.config.sys { return quote! { #name: #type_name, }; } - if param.flags().contains(ParamAttributes::Out) { - if ty.deref().is_interface() { - let type_name = ty.deref().write_name(writer); - quote! { #name: windows_core::OutRef<'_, #type_name>, } + if param.is_input() { + if param.is_copyable() { + return quote! { #name: #type_name, }; } else { - quote! { #name: #type_name, } + return quote! { #name: windows_core::Ref<'_, #type_name>, }; } - } else if ty.is_copyable() { - quote! { #name: #type_name, } + } + + let deref = param.deref(); + + if deref.is_interface() { + let type_name = deref.write_name(writer); + quote! { #name: windows_core::OutRef<'_, #type_name>, } } else { - quote! { #name: windows_core::Ref<'_, #type_name>, } + quote! { #name: #type_name, } } } diff --git a/crates/libs/bindgen/src/types/cpp_fn.rs b/crates/libs/bindgen/src/types/cpp_fn.rs index cc804c2f6e..eb48065edb 100644 --- a/crates/libs/bindgen/src/types/cpp_fn.rs +++ b/crates/libs/bindgen/src/types/cpp_fn.rs @@ -50,12 +50,12 @@ impl CppFn { let signature = self.method.signature(self.namespace, &[]); - let params = signature.params.iter().map(|(ty, param)| { - let name = to_ident(¶m.name().to_lowercase()); + let params = signature.params.iter().map(|param| { + let name = param.write_ident(); let ty = if underlying_types { - ty.underlying_type().write_abi(writer) + param.underlying_type().write_abi(writer) } else { - ty.write_abi(writer) + param.write_abi(writer) }; quote! { #name: #ty } }); @@ -143,7 +143,7 @@ impl CppFn { } ReturnHint::ResultValue => { let where_clause = method.write_where(writer, false); - let return_type = signature.params[signature.params.len() - 1].0.deref(); + let return_type = signature.params[signature.params.len() - 1].deref(); let map = return_type.write_result_map(); let return_type = return_type.write_name(writer); @@ -174,9 +174,8 @@ impl CppFn { ReturnHint::ReturnValue => { let where_clause = method.write_where(writer, false); - let return_type = method.signature.params[method.signature.params.len() - 1] - .0 - .deref(); + let return_type = + method.signature.params[method.signature.params.len() - 1].deref(); if return_type.is_interface() { let return_type = return_type.write_name(writer); @@ -221,7 +220,7 @@ impl CppFn { let where_clause = method.write_where(writer, false); if method.handle_last_error() { - let return_type = signature.return_type.0.write_name(writer); + let return_type = signature.return_type.write_name(writer); quote! { #cfg @@ -302,7 +301,7 @@ impl Writer { signature: &Signature, underlying_types: bool, ) -> TokenStream { - match &signature.return_type.0 { + match &signature.return_type { Type::Void => { if method.has_attribute("DoesNotReturnAttribute") { quote! { -> ! } diff --git a/crates/libs/bindgen/src/types/cpp_method.rs b/crates/libs/bindgen/src/types/cpp_method.rs index e00ad80b37..b13f5ab97f 100644 --- a/crates/libs/bindgen/src/types/cpp_method.rs +++ b/crates/libs/bindgen/src/types/cpp_method.rs @@ -34,9 +34,9 @@ pub enum ParamHint { Bool, } -impl ParamHint { - fn from_param(param: Param) -> Self { - for attribute in param.attributes() { +impl From<&Param> for ParamHint { + fn from(param: &Param) -> Self { + for attribute in param.def.attributes() { match attribute.name() { "NativeArrayInfoAttribute" => { for (_, value) in attribute.args() { @@ -61,7 +61,9 @@ impl ParamHint { } ParamHint::None } +} +impl ParamHint { fn is_array(&self) -> bool { matches!( self, @@ -79,8 +81,8 @@ impl CppMethod { let mut param_hints = vec![ParamHint::None; signature.params.len()]; - for (position, (_, param)) in signature.params.iter().enumerate() { - param_hints[position] = ParamHint::from_param(*param); + for (position, param) in signature.params.iter().enumerate() { + param_hints[position] = param.into(); } let mut dependencies = TypeMap::new(); @@ -92,12 +94,9 @@ impl CppMethod { ParamHint::ArrayRelativeLen(relative) | ParamHint::ArrayRelativeByteLen(relative) => { // The len params must be input only. - if !signature.params[relative] - .1 - .flags() - .contains(ParamAttributes::Out) + if signature.params[relative].is_input() && position != relative - && !signature.params[relative].0.is_pointer() + && !signature.params[relative].is_pointer() { param_hints[relative] = ParamHint::ArrayRelativePtr(position); } else { @@ -106,7 +105,7 @@ impl CppMethod { } ParamHint::ArrayFixed(_) => { if signature.params[position] - .1 + .def .has_attribute("FreeWithAttribute") { param_hints[position] = ParamHint::None; @@ -142,7 +141,7 @@ impl CppMethod { // Remove any byte arrays that aren't byte-sized types. for position in 0..param_hints.len() { if let ParamHint::ArrayRelativeByteLen(relative) = param_hints[position] { - if !signature.params[position].0.is_byte_size() { + if !signature.params[position].is_byte_size() { param_hints[position] = ParamHint::None; param_hints[relative] = ParamHint::None; } @@ -151,28 +150,25 @@ impl CppMethod { for (position, hint) in param_hints.iter_mut().enumerate() { if *hint == ParamHint::None { - let ty = &signature.params[position].0; - let param = signature.params[position].1; - let flags = param.flags(); + let param = &signature.params[position]; - if is_convertible(ty, param, *hint) { + if param.is_convertible() && !hint.is_array() { *hint = ParamHint::IntoParam; - } else if ty.is_copyable() - && (flags.contains(ParamAttributes::Optional) - || param.has_attribute("ReservedAttribute")) - { + } else if param.is_copyable() && param.is_optional() { *hint = ParamHint::Optional; - } else if !flags.contains(ParamAttributes::Out) && *ty == Type::BOOL { + } else if param.is_input() && param.ty == Type::BOOL { *hint = ParamHint::Bool; - } else if ty.is_primitive() && (!ty.is_pointer() || ty.deref().is_copyable()) { + } else if param.is_primitive() + && (!param.is_pointer() || param.deref().is_copyable()) + { *hint = ParamHint::ValueType; - } else if ty.is_copyable() { + } else if param.is_copyable() { *hint = ParamHint::Blittable; } } } - let is_retval = is_retval(&signature, ¶m_hints); + let is_retval = signature.is_retval(); let mut return_hint = ReturnHint::None; let last_error = if let Some(map) = def.impl_map() { @@ -182,7 +178,7 @@ impl CppMethod { }; if !def.has_attribute("CanReturnMultipleSuccessValuesAttribute") { - match &signature.return_type.0 { + match &signature.return_type { Type::Void if is_retval => return_hint = ReturnHint::ReturnValue, Type::HRESULT => { if is_retval { @@ -193,11 +189,7 @@ impl CppMethod { if signature.params.len() >= 2 { if let Some((guid, object)) = signature_param_is_query(&signature.params) { - if signature.params[object] - .1 - .flags() - .contains(ParamAttributes::Optional) - { + if signature.params[object].is_optional() { return_hint = ReturnHint::QueryOptional(object, guid); } else { return_hint = ReturnHint::Query(object, guid); @@ -251,10 +243,10 @@ impl CppMethod { pub fn write_where(&self, writer: &Writer, query: bool) -> TokenStream { let mut tokens = quote! {}; - for (position, (ty, _)) in self.signature.params.iter().enumerate() { + for (position, param) in self.signature.params.iter().enumerate() { if self.param_hints[position] == ParamHint::IntoParam { let name: TokenStream = format!("P{position}").into(); - let into = ty.write_name(writer); + let into = param.write_name(writer); tokens.combine(quote! { #name: windows_core::Param<#into>, }) } } @@ -307,9 +299,7 @@ impl CppMethod { ReturnHint::ResultValue => { let where_clause = self.write_where(writer, false); - let return_type = self.signature.params[self.signature.params.len() - 1] - .0 - .deref(); + let return_type = self.signature.params[self.signature.params.len() - 1].deref(); let map = return_type.write_result_map(); let return_type = return_type.write_name(writer); @@ -335,9 +325,7 @@ impl CppMethod { ReturnHint::ReturnValue => { let where_clause = self.write_where(writer, false); - let return_type = self.signature.params[self.signature.params.len() - 1] - .0 - .deref(); + let return_type = self.signature.params[self.signature.params.len() - 1].deref(); if return_type.is_interface() { let return_type = return_type.write_name(writer); @@ -373,7 +361,7 @@ impl CppMethod { } } ReturnHint::ReturnStruct => { - let return_type = self.signature.return_type.0.write_name(writer); + let return_type = self.signature.return_type.write_name(writer); let where_clause = self.write_where(writer, false); quote! { @@ -403,17 +391,9 @@ impl CppMethod { ReturnHint::ResultValue => { let invoke_args = self.signature.params[..self.signature.params.len() - 1] .iter() - .enumerate() - .map(|(position, param)| { - write_invoke_arg(¶m.0, param.1, self.param_hints[position]) - }); - - let result = to_ident( - &self.signature.params[self.signature.params.len() - 1] - .1 - .name() - .to_lowercase(), - ); + .map(write_invoke_arg); + + let result = self.signature.params[self.signature.params.len() - 1].write_ident(); quote! { match #parent_impl::#name(this, #(#invoke_args,)*) { @@ -427,42 +407,21 @@ impl CppMethod { } } ReturnHint::Query(..) | ReturnHint::QueryOptional(..) | ReturnHint::ResultVoid => { - let invoke_args = - self.signature - .params - .iter() - .enumerate() - .map(|(position, param)| { - write_invoke_arg(¶m.0, param.1, self.param_hints[position]) - }); + let invoke_args = self.signature.params.iter().map(write_invoke_arg); quote! { #parent_impl::#name(this, #(#invoke_args,)*).into() } } ReturnHint::ReturnStruct => { - let invoke_args = - self.signature - .params - .iter() - .enumerate() - .map(|(position, param)| { - write_invoke_arg(¶m.0, param.1, self.param_hints[position]) - }); + let invoke_args = self.signature.params.iter().map(write_invoke_arg); quote! { *result__ = #parent_impl::#name(this, #(#invoke_args,)*) } } _ => { - let invoke_args = - self.signature - .params - .iter() - .enumerate() - .map(|(position, param)| { - write_invoke_arg(¶m.0, param.1, self.param_hints[position]) - }); + let invoke_args = self.signature.params.iter().map(write_invoke_arg); quote! { #parent_impl::#name(this, #(#invoke_args,)*) @@ -475,12 +434,12 @@ impl CppMethod { let mut params = quote! {}; if self.return_hint == ReturnHint::ResultValue { - for (ty, param) in &self.signature.params[..self.signature.params.len() - 1] { - params.combine(write_produce_type(writer, ty, *param)); + for param in &self.signature.params[..self.signature.params.len() - 1] { + params.combine(write_produce_type(writer, param)); } } else { - for (ty, param) in &self.signature.params { - params.combine(write_produce_type(writer, ty, *param)); + for param in &self.signature.params { + params.combine(write_produce_type(writer, param)); } } @@ -489,9 +448,7 @@ impl CppMethod { quote! { -> windows_core::Result<()> } } ReturnHint::ResultValue => { - let return_type = self.signature.params[self.signature.params.len() - 1] - .0 - .deref(); + let return_type = self.signature.params[self.signature.params.len() - 1].deref(); let return_type = return_type.write_name(writer); quote! { -> windows_core::Result<#return_type> } @@ -507,11 +464,11 @@ impl CppMethod { .signature .params .iter() - .map(|(ty, param)| { - let ty = ty.write_abi(writer); + .map(|param| { + let ty = param.write_abi(writer); if named_params { - let name = to_ident(¶m.name().to_lowercase()); + let name = param.write_ident(); quote! { #name: #ty } } else { ty @@ -523,7 +480,7 @@ impl CppMethod { match self.return_hint { ReturnHint::ReturnStruct => { - let return_type = self.signature.return_type.0.write_abi(writer); + let return_type = self.signature.return_type.write_abi(writer); if named_params { params.insert(0, quote! { result__: *mut #return_type }); @@ -548,7 +505,7 @@ impl CppMethod { pub fn write_params(&self, writer: &Writer) -> TokenStream { let mut tokens = quote! {}; - for (position, (ty, param)) in self.signature.params.iter().enumerate() { + for (position, param) in self.signature.params.iter().enumerate() { match self.return_hint { ReturnHint::Query(object, guid) | ReturnHint::QueryOptional(object, guid) => { if object == position || guid == position { @@ -563,45 +520,45 @@ impl CppMethod { _ => {} } - let name = to_ident(¶m.name().to_lowercase()); + let name = param.write_ident(); match self.param_hints[position] { ParamHint::ArrayFixed(fixed) => { - let ty = ty.deref(); + let ty = param.deref(); let ty = ty.write_default(writer); let len = Literal::u32_unsuffixed(fixed as u32); - let ty = if param.flags().contains(ParamAttributes::Out) { - quote! { &mut [#ty; #len] } - } else { + let ty = if param.is_input() { quote! { &[#ty; #len] } + } else { + quote! { &mut [#ty; #len] } }; - if param.flags().contains(ParamAttributes::Optional) { + if param.is_optional() { tokens.combine("e! { #name: Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); } } ParamHint::ArrayRelativeLen(_) => { - let ty = ty.deref(); + let ty = param.deref(); let ty = ty.write_default(writer); - let ty = if param.flags().contains(ParamAttributes::Out) { - quote! { &mut [#ty] } - } else { + let ty = if param.is_input() { quote! { &[#ty] } + } else { + quote! { &mut [#ty] } }; - if param.flags().contains(ParamAttributes::Optional) { + if param.is_optional() { tokens.combine("e! { #name: Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); } } ParamHint::ArrayRelativeByteLen(_) => { - let ty = if param.flags().contains(ParamAttributes::Out) { - quote! { &mut [u8] } - } else { + let ty = if param.is_input() { quote! { &[u8] } + } else { + quote! { &mut [u8] } }; - if param.flags().contains(ParamAttributes::Optional) { + if param.is_optional() { tokens.combine("e! { #name: Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); @@ -613,11 +570,11 @@ impl CppMethod { tokens.combine("e! { #name: #kind, }); } ParamHint::Optional => { - if matches!(ty, Type::CppDelegate(..)) { - let kind = ty.write_name(writer); + if matches!(param.ty, Type::CppDelegate(..)) { + let kind = param.write_name(writer); tokens.combine("e! { #name: #kind, }); } else { - let kind = ty.write_name(writer); + let kind = param.write_name(writer); tokens.combine("e! { #name: Option<#kind>, }); } } @@ -625,11 +582,11 @@ impl CppMethod { tokens.combine("e! { #name: bool, }); } ParamHint::ValueType | ParamHint::Blittable => { - let kind = ty.write_default(writer); + let kind = param.write_default(writer); tokens.combine("e! { #name: #kind, }); } ParamHint::None => { - let kind = ty.write_default(writer); + let kind = param.write_default(writer); tokens.combine("e! { #name: &#kind, }); } } @@ -641,7 +598,7 @@ impl CppMethod { pub fn write_args(&self) -> TokenStream { let mut tokens = quote! {}; - for (position, (ty, param)) in self.signature.params.iter().enumerate() { + for (position, param) in self.signature.params.iter().enumerate() { let new = match self.return_hint { ReturnHint::Query(object, _) if object == position => { quote! { &mut result__, } @@ -660,13 +617,12 @@ impl CppMethod { quote! { &T::IID, } } _ => { - let name = to_ident(¶m.name().to_lowercase()); - let flags = param.flags(); + let name = param.write_ident(); match self.param_hints[position] { ParamHint::ArrayFixed(_) | ParamHint::ArrayRelativeLen(_) | ParamHint::ArrayRelativeByteLen(_) => { - let map = if flags.contains(ParamAttributes::Optional) { + let map = if param.is_optional() { quote! { #name.as_deref().map_or(core::ptr::null(), |slice|slice.as_ptr()) } } else { quote! { #name.as_ptr() } @@ -674,10 +630,9 @@ impl CppMethod { quote! { core::mem::transmute(#map), } } ParamHint::ArrayRelativePtr(relative) => { - let name = - to_ident(&self.signature.params[relative].1.name().to_lowercase()); - let flags = self.signature.params[relative].1.flags(); - if flags.contains(ParamAttributes::Optional) { + let relative_param = &self.signature.params[relative]; + let name = relative_param.write_ident(); + if relative_param.is_optional() { quote! { #name.as_deref().map_or(0, |slice|slice.len().try_into().unwrap()), } } else { quote! { #name.len().try_into().unwrap(), } @@ -687,7 +642,7 @@ impl CppMethod { quote! { #name.param().abi(), } } ParamHint::Optional => { - if matches!(ty, Type::CppDelegate(..)) { + if matches!(param.ty, Type::CppDelegate(..)) { quote! { #name, } } else { quote! { #name.unwrap_or(core::mem::zeroed()) as _, } @@ -697,14 +652,14 @@ impl CppMethod { quote! { #name.into(), } } ParamHint::ValueType => { - if flags.contains(ParamAttributes::Out) { - quote! { #name as _, } - } else { + if param.is_input() { quote! { #name, } + } else { + quote! { #name as _, } } } ParamHint::Blittable => { - if matches!(ty, Type::PrimitiveOrEnum(_, _)) { + if matches!(param.ty, Type::PrimitiveOrEnum(_, _)) { quote! { #name.0 as _, } } else { quote! { core::mem::transmute(#name), } @@ -723,7 +678,7 @@ impl CppMethod { } pub fn write_return(&self, writer: &Writer) -> TokenStream { - match &self.signature.return_type.0 { + match &self.signature.return_type { Type::Void if self.def.has_attribute("DoesNotReturnAttribute") => quote! { -> ! }, Type::Void => quote! {}, ty => { @@ -736,7 +691,7 @@ impl CppMethod { pub fn handle_last_error(&self) -> bool { if let Some(map) = self.def.impl_map() { if map.flags().contains(PInvokeAttributes::SupportsLastError) { - if let Type::CppStruct(ty) = &self.signature.return_type.0 { + if let Type::CppStruct(ty) = &self.signature.return_type { if ty.is_handle() { // https://github.com/microsoft/windows-rs/issues/2392#issuecomment-1477765781 if self.def.name() == "LocalFree" { @@ -756,18 +711,18 @@ impl CppMethod { } } -fn write_produce_type(writer: &Writer, ty: &Type, param: Param) -> TokenStream { - let name = to_ident(¶m.name().to_lowercase()); - let kind = ty.write_default(writer); +fn write_produce_type(writer: &Writer, param: &Param) -> TokenStream { + let name = param.write_ident(); + let kind = param.write_default(writer); - if !param.flags().contains(ParamAttributes::Out) && ty.is_interface() { - let type_name = ty.write_name(writer); + if param.is_input() && param.is_interface() { + let type_name = param.write_name(writer); quote! { #name: windows_core::Ref<'_, #type_name>, } - } else if param.flags().contains(ParamAttributes::Out) && ty.deref().is_interface() { - let type_name = ty.deref().write_name(writer); + } else if !param.is_input() && param.deref().is_interface() { + let type_name = param.deref().write_name(writer); quote! { #name: windows_core::OutRef<'_, #type_name>, } - } else if !param.flags().contains(ParamAttributes::Out) { - if ty.is_primitive() { + } else if param.is_input() { + if param.is_primitive() { quote! { #name: #kind, } } else { quote! { #name: &#kind, } @@ -777,13 +732,13 @@ fn write_produce_type(writer: &Writer, ty: &Type, param: Param) -> TokenStream { } } -fn write_invoke_arg(ty: &Type, param: Param, _hint: ParamHint) -> TokenStream { - let name = to_ident(¶m.name().to_lowercase()); +fn write_invoke_arg(param: &Param) -> TokenStream { + let name = param.write_ident(); - if !param.flags().contains(ParamAttributes::Out) && ty.is_interface() { + if param.is_input() && param.is_interface() { quote! { core::mem::transmute_copy(&#name) } - } else if (!ty.is_pointer() && ty.is_interface()) - || (!param.flags().contains(ParamAttributes::Out) && !ty.is_primitive()) + } else if (!param.is_pointer() && param.is_interface()) + || (param.is_input() && !param.is_primitive()) { quote! { core::mem::transmute(&#name) } } else { @@ -791,70 +746,14 @@ fn write_invoke_arg(ty: &Type, param: Param, _hint: ParamHint) -> TokenStream { } } -fn is_convertible(ty: &Type, param: Param, hint: ParamHint) -> bool { - !param.flags().contains(ParamAttributes::Out) && !hint.is_array() && ty.is_convertible() -} - -fn is_retval(signature: &Signature, param_hints: &[ParamHint]) -> bool { - // First we check whether there's an actual retval parameter. - if let Some(param) = signature.params.last() { - if param.1.has_attribute("RetValAttribute") { - return true; - } - } - - if let Some((ty, param)) = signature.params.last() { - if is_param_retval(ty, *param, param_hints[param_hints.len() - 1]) { - return signature.params[..signature.params.len() - 1] - .iter() - .all(|(_, param)| !param.flags().contains(ParamAttributes::Out)); - } - } - - false -} - -fn is_param_retval(ty: &Type, param: Param, hint: ParamHint) -> bool { - // The Win32 metadata uses `RetValAttribute` to call out retval methods but it is employed - // very sparingly, so this heuristic is used to apply the transformation more uniformly. - if param.has_attribute("RetValAttribute") { - return true; - } - if !ty.is_pointer() { - return false; - } - if ty.is_void() { - return false; - } - let flags = param.flags(); - if flags.contains(ParamAttributes::In) - || !flags.contains(ParamAttributes::Out) - || flags.contains(ParamAttributes::Optional) - || hint.is_array() +fn signature_param_is_query(params: &[Param]) -> Option<(usize, usize)> { + if let Some(guid) = params + .iter() + .rposition(|param| param.ty == Type::PtrConst(Box::new(Type::GUID), 1) && param.is_input()) { - return false; - } - // This is reevaluated to detect unsupported array parameters. - // https://github.com/microsoft/windows-rs/issues/3384 - if ParamHint::from_param(param).is_array() { - return false; - } - - // If it's bigger than 128 bits, best to pass as a reference. - if ty.deref().size() > 16 { - return false; - } - true -} - -fn signature_param_is_query(params: &[(Type, Param)]) -> Option<(usize, usize)> { - if let Some(guid) = params.iter().rposition(|(ty, param)| { - *ty == Type::PtrConst(Box::new(Type::GUID), 1) - && !param.flags().contains(ParamAttributes::Out) - }) { - if let Some(object) = params.iter().rposition(|(ty, param)| { - *ty == Type::PtrMut(Box::new(Type::Void), 2) - && param.has_attribute("ComOutPtrAttribute") + if let Some(object) = params.iter().rposition(|param| { + param.ty == Type::PtrMut(Box::new(Type::Void), 2) + && param.def.has_attribute("ComOutPtrAttribute") }) { return Some((guid, object)); } diff --git a/crates/libs/bindgen/src/types/method.rs b/crates/libs/bindgen/src/types/method.rs index 3644223969..0d1c8fd334 100644 --- a/crates/libs/bindgen/src/types/method.rs +++ b/crates/libs/bindgen/src/types/method.rs @@ -39,22 +39,22 @@ impl Method { .params .iter() .map(|param| { - let name = to_ident(¶m.1.name().to_lowercase()); - let abi_size_name: TokenStream = format!("{}_array_size", param.1.name().to_lowercase()).into(); + let name = param.write_ident(); + let abi_size_name: TokenStream = format!("{}_array_size", param.write_ident()).into(); - if param.1.flags().contains(ParamAttributes::In) { - if param.0.is_winrt_array() { + if param.is_input() { + if param.is_winrt_array() { quote! { core::slice::from_raw_parts(core::mem::transmute_copy(&#name), #abi_size_name as usize) } - } else if param.0.is_primitive() { + } else if param.is_primitive() { quote! { #name } - } else if param.0.is_const_ref() || param.0.is_interface() || matches!(¶m.0, Type::Param(_)) { + } else if param.is_const_ref() || param.is_interface() || matches!(¶m.ty, Type::Generic(_)) { quote! { core::mem::transmute_copy(&#name) } } else { quote! { core::mem::transmute(&#name) } } - } else if param.0.is_winrt_array() { + } else if param.is_winrt_array() { quote! { core::slice::from_raw_parts_mut(core::mem::transmute_copy(&#name), #abi_size_name as usize) } - } else if param.0.is_winrt_array_ref() { + } else if param.is_winrt_array_ref() { quote! { windows_core::ArrayProxy::from_raw_parts(core::mem::transmute_copy(&#name), #abi_size_name).as_array() } } else { quote! { core::mem::transmute_copy(&#name) } @@ -67,7 +67,7 @@ impl Method { quote! {} }; - match &self.signature.return_type.0 { + match &self.signature.return_type { Type::Void => { if noexcept { quote! { @@ -80,7 +80,7 @@ impl Method { } } } - _ if self.signature.return_type.0.is_winrt_array() => { + _ if self.signature.return_type.is_winrt_array() => { if noexcept { quote! { let ok__ = #inner(#this #(#invoke_args,)*); @@ -105,7 +105,7 @@ impl Method { } } _ => { - let forget = if self.signature.return_type.0.is_copyable() { + let forget = if self.signature.return_type.is_copyable() { quote! {} } else { quote! { core::mem::forget(ok__); } @@ -145,45 +145,45 @@ impl Method { let noexcept = self.def.has_attribute("NoExceptionAttribute"); let params = self.signature.params.iter().map(|p| { - let default_type = p.0.write_default(writer); + let default_type = p.write_default(writer); - let sig = if p.1.flags().contains(ParamAttributes::In) { - if p.0.is_winrt_array() { + let sig = if p.is_input() { + if p.is_winrt_array() { quote! { &[#default_type] } - } else if p.0.is_primitive() { + } else if p.is_primitive() { quote! { #default_type } - } else if p.0.is_interface() || matches!(&p.0, Type::Param(_)) { - let type_name = p.0.write_name(writer); + } else if p.is_interface() || matches!(&p.ty, Type::Generic(_)) { + let type_name = p.write_name(writer); quote! { windows_core::Ref<'_, #type_name> } } else { quote! { &#default_type } } - } else if p.0.is_winrt_array() { + } else if p.is_winrt_array() { quote! { &mut [#default_type] } - } else if p.0.is_winrt_array_ref() { - let kind = p.0.write_name(writer); + } else if p.is_winrt_array_ref() { + let kind = p.write_name(writer); quote! { &mut windows_core::Array<#kind> } - } else if p.0.is_interface() { - let type_name = p.0.write_name(writer); + } else if p.is_interface() { + let type_name = p.write_name(writer); quote! { windows_core::OutRef<'_, #type_name> } } else { quote! { &mut #default_type } }; if named_params { - let name = to_ident(p.1.name()); + let name = to_ident(p.def.name()); quote! { #name: #sig } } else { sig } }); - let return_type_tokens = if self.signature.return_type.0 == Type::Void { + let return_type_tokens = if self.signature.return_type == Type::Void { quote! { () } } else { - let tokens = self.signature.return_type.0.write_name(writer); + let tokens = self.signature.return_type.write_name(writer); - if self.signature.return_type.0.is_winrt_array() { + if self.signature.return_type.is_winrt_array() { quote! { windows_core::Array<#tokens> } } else { tokens @@ -191,9 +191,9 @@ impl Method { }; let return_type_tokens = if noexcept { - if self.signature.return_type.0.is_interface() { + if self.signature.return_type.is_interface() { quote! { -> Option<#return_type_tokens> } - } else if self.signature.return_type.0 == Type::Void { + } else if self.signature.return_type == Type::Void { quote! {} } else { quote! { -> #return_type_tokens } @@ -215,18 +215,18 @@ impl Method { pub fn write_abi(&self, writer: &Writer, named_params: bool) -> TokenStream { let args = self.signature.params.iter().map(|param| { - let name = to_ident(¶m.1.name().to_lowercase()); - let abi = param.0.write_abi(writer); + let name = param.write_ident(); + let abi = param.write_abi(writer); let abi_size_name: TokenStream = format!("{}_array_size", name.as_str()).into(); - if param.1.flags().contains(ParamAttributes::In) { - if param.0.is_winrt_array() { + if param.is_input() { + if param.is_winrt_array() { if named_params { quote! { #abi_size_name: u32, #name: *const #abi } } else { quote! { u32, *const #abi } } - } else if param.0.is_const_ref() { + } else if param.is_const_ref() { if named_params { quote! { #name: &#abi } } else { @@ -237,13 +237,13 @@ impl Method { } else { quote! { #abi } } - } else if param.0.is_winrt_array() { + } else if param.is_winrt_array() { if named_params { quote! { #abi_size_name: u32, #name: *mut #abi } } else { quote! { u32, *mut #abi } } - } else if param.0.is_winrt_array_ref() { + } else if param.is_winrt_array_ref() { if named_params { quote! { #abi_size_name: *mut u32, #name: *mut *mut #abi } } else { @@ -256,7 +256,7 @@ impl Method { } }); - let return_arg = match &self.signature.return_type.0 { + let return_arg = match &self.signature.return_type { Type::Void => quote! {}, Type::Array(ty) => { let ty = ty.write_abi(writer); @@ -309,19 +309,19 @@ impl Method { let args = { let args = params.iter().map(|param|{ - let name = to_ident(¶m.1.name().to_lowercase()); + let name = param.write_ident(); - if param.1.flags().contains(ParamAttributes::In) { - if param.0.is_winrt_array() { - if param.0.is_copyable() { + if param.is_input() { + if param.is_winrt_array() { + if param.is_copyable() { quote! { #name.len().try_into().unwrap(), #name.as_ptr() } } else { quote! { #name.len().try_into().unwrap(), core::mem::transmute(#name.as_ptr()) } } - } else if param.0.is_convertible() { + } else if param.is_convertible() { quote! { #name.param().abi() } - } else if param.0.is_copyable() { - if param.0.is_const_ref() { + } else if param.is_copyable() { + if param.is_const_ref() { quote! { &#name } } else { quote! { #name } @@ -329,22 +329,22 @@ impl Method { } else { quote! { core::mem::transmute_copy(#name) } } - } else if param.0.is_winrt_array() { - if param.0.is_copyable() { + } else if param.is_winrt_array() { + if param.is_copyable() { quote! { #name.len().try_into().unwrap(), #name.as_mut_ptr() } } else { quote! { #name.len().try_into().unwrap(), core::mem::transmute_copy(&#name) } } - } else if param.0.is_winrt_array_ref() { + } else if param.is_winrt_array_ref() { quote! { #name.set_abi_len(), #name as *mut _ as _ } - } else if param.0.is_copyable() { + } else if param.is_copyable() { quote! { #name } } else { quote! { #name as *mut _ as _ } } }); - let return_arg = match &self.signature.return_type.0 { + let return_arg = match &self.signature.return_type { Type::Void => quote! {}, ty => { if ty.is_winrt_array() { @@ -367,26 +367,23 @@ impl Method { } }; - let generics = params - .iter() - .enumerate() - .filter_map(|(position, (ty, def))| { - if is_convertible(ty, *def) { - let name: TokenStream = format!("P{position}").into(); - Some(name) - } else { - None - } - }); + let generics = params.iter().enumerate().filter_map(|(position, param)| { + if param.is_convertible() { + let name: TokenStream = format!("P{position}").into(); + Some(name) + } else { + None + } + }); let where_clause = { let constraints: Vec<_> = params .iter() .enumerate() - .filter_map(|(position, (ty, def))| { - if is_convertible(ty, *def) { + .filter_map(|(position, param)| { + if param.is_convertible() { let name: TokenStream = format!("P{position}").into(); - let ty = ty.write_name(writer); + let ty = param.write_name(writer); Some(quote! { #name: windows_core::Param<#ty>, }) } else { @@ -403,35 +400,35 @@ impl Method { }; let params = params.iter().enumerate().map(|(position, param)| { - let name = to_ident(¶m.1.name().to_lowercase()); - let kind = param.0.write_name(writer); - let default_type = param.0.write_default(writer); + let name = param.write_ident(); + let kind = param.write_name(writer); + let default_type = param.write_default(writer); - if param.1.flags().contains(ParamAttributes::In) { - if param.0.is_winrt_array() { + if param.is_input() { + if param.is_winrt_array() { quote! { #name: &[#default_type], } - } else if is_convertible(¶m.0, param.1) { + } else if param.is_convertible() { let kind: TokenStream = format!("P{position}").into(); quote! { #name: #kind, } - } else if param.0.is_copyable() { + } else if param.is_copyable() { quote! { #name: #kind, } } else { quote! { #name: &#kind, } } - } else if param.0.is_winrt_array() { + } else if param.is_winrt_array() { quote! { #name: &mut [#default_type], } - } else if param.0.is_winrt_array_ref() { + } else if param.is_winrt_array_ref() { quote! { #name: &mut windows_core::Array<#kind>, } } else { quote! { #name: &mut #default_type, } } }); - let return_type = match &self.signature.return_type.0 { + let return_type = match &self.signature.return_type { Type::Void => quote! { () }, _ => { - let tokens = self.signature.return_type.0.write_name(writer); - if self.signature.return_type.0.is_winrt_array() { + let tokens = self.signature.return_type.write_name(writer); + if self.signature.return_type.is_winrt_array() { quote! { windows_core::Array<#tokens> } } else { quote! { #tokens } @@ -442,9 +439,9 @@ impl Method { let noexcept = self.def.has_attribute("NoExceptionAttribute"); let return_type = if noexcept { - if self.signature.return_type.0.is_interface() { + if self.signature.return_type.is_interface() { quote! { -> Option<#return_type> } - } else if self.signature.return_type.0 == Type::Void { + } else if self.signature.return_type == Type::Void { quote! {} } else { quote! { -> #return_type } @@ -456,7 +453,7 @@ impl Method { let vname = virtual_names.add(self.def); let vcall = quote! { (windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args) }; - let vcall = match &self.signature.return_type.0 { + let vcall = match &self.signature.return_type { Type::Void => { if noexcept { quote! { @@ -469,7 +466,7 @@ impl Method { } } } - _ if self.signature.return_type.0.is_winrt_array() => { + _ if self.signature.return_type.is_winrt_array() => { if noexcept { quote! { let mut result__ = core::mem::MaybeUninit::zeroed(); @@ -487,7 +484,7 @@ impl Method { } _ => { if noexcept { - if self.signature.return_type.0.is_copyable() { + if self.signature.return_type.is_copyable() { quote! { let mut result__ = core::mem::zeroed(); let hresult__ = #vcall; @@ -503,7 +500,7 @@ impl Method { } } } else { - let map = self.signature.return_type.0.write_result_map(); + let map = self.signature.return_type.write_result_map(); quote! { let mut result__ = core::mem::zeroed(); @@ -552,7 +549,3 @@ impl Method { } } } - -fn is_convertible(ty: &Type, param: Param) -> bool { - param.flags().contains(ParamAttributes::In) && ty.is_convertible() -} diff --git a/crates/libs/bindgen/src/types/mod.rs b/crates/libs/bindgen/src/types/mod.rs index 10f1b21ca2..e258d4641f 100644 --- a/crates/libs/bindgen/src/types/mod.rs +++ b/crates/libs/bindgen/src/types/mod.rs @@ -42,7 +42,7 @@ pub enum Type { CppStruct(CppStruct), CppConst(CppConst), - Param(&'static str), + Generic(&'static str), PtrMut(Box, usize), PtrConst(Box, usize), ArrayFixed(Box, usize), @@ -137,7 +137,7 @@ impl Type { fn is_intrinsic(&self) -> bool { matches!( self, - Self::Param(..) + Self::Generic(..) | Self::Void | Self::Bool | Self::Char @@ -440,7 +440,7 @@ impl Type { Self::CppDelegate(ty) => ty.write_name(writer), Self::Delegate(ty) => ty.write_name(writer), Self::Class(ty) => ty.write_name(writer), - Self::Param(param) => to_ident(param), + Self::Generic(param) => to_ident(param), Self::PtrMut(ty, pointers) => { let pointers = write_ptr_mut(*pointers); let ty = ty.write_default(writer); @@ -480,7 +480,7 @@ impl Type { } else { let tokens = self.write_name(writer); - if matches!(self, Self::Param(_)) { + if matches!(self, Self::Generic(_)) { quote! { <#tokens as windows_core::Type<#tokens>>::Default } } else if self.is_interface() { quote! { Option<#tokens> } @@ -521,7 +521,7 @@ impl Type { let len = Literal::usize_unsuffixed(*len); quote! { [#name; #len] } } - Self::Param(name) => { + Self::Generic(name) => { let name = to_ident(name); quote! { windows_core::AbiType<#name> } } @@ -716,7 +716,7 @@ impl Type { false } - Self::String | Self::BSTR | Self::Object | Self::IUnknown | Self::Param(_) => false, + Self::String | Self::BSTR | Self::Object | Self::IUnknown | Self::Generic(_) => false, Self::ArrayFixed(ty, _) => ty.is_copyable(), Self::Array(ty) => ty.is_copyable(), _ => true, @@ -744,7 +744,7 @@ impl Type { | Self::PCWSTR | Self::Object | Self::IUnknown - | Self::Param(_) + | Self::Generic(_) ) } diff --git a/crates/libs/bindgen/src/winmd/codes.rs b/crates/libs/bindgen/src/winmd/codes.rs index 77d650487a..e462f8b791 100644 --- a/crates/libs/bindgen/src/winmd/codes.rs +++ b/crates/libs/bindgen/src/winmd/codes.rs @@ -46,7 +46,7 @@ code! { HasAttribute(5) (Field, 1) (TypeRef, 2) (TypeDef, 3) - (Param, 4) + (MethodParam, 4) (InterfaceImpl, 5) (MemberRef, 6) (TypeSpec, 13) diff --git a/crates/libs/bindgen/src/winmd/file.rs b/crates/libs/bindgen/src/winmd/file.rs index 7c707c83fb..8a3ff1f258 100644 --- a/crates/libs/bindgen/src/winmd/file.rs +++ b/crates/libs/bindgen/src/winmd/file.rs @@ -187,7 +187,7 @@ impl File { 0x02 => result.tables[TypeDef::TABLE].len = len, 0x04 => result.tables[Field::TABLE].len = len, 0x06 => result.tables[MethodDef::TABLE].len = len, - 0x08 => result.tables[Param::TABLE].len = len, + 0x08 => result.tables[MethodParam::TABLE].len = len, 0x09 => result.tables[InterfaceImpl::TABLE].len = len, 0x0a => result.tables[MemberRef::TABLE].len = len, 0x0b => result.tables[Constant::TABLE].len = len, @@ -232,11 +232,11 @@ impl File { ]); let has_constant = coded_index_size(&[ tables[Field::TABLE].len, - tables[Param::TABLE].len, + tables[MethodParam::TABLE].len, unused_property.len, ]); let has_field_marshal = - coded_index_size(&[tables[Field::TABLE].len, tables[Param::TABLE].len]); + coded_index_size(&[tables[Field::TABLE].len, tables[MethodParam::TABLE].len]); let has_decl_security = coded_index_size(&[ tables[TypeDef::TABLE].len, tables[MethodDef::TABLE].len, @@ -280,7 +280,7 @@ impl File { tables[Field::TABLE].len, tables[TypeRef::TABLE].len, tables[TypeDef::TABLE].len, - tables[Param::TABLE].len, + tables[MethodParam::TABLE].len, tables[InterfaceImpl::TABLE].len, tables[MemberRef::TABLE].len, unused_module.len, @@ -406,7 +406,7 @@ impl File { 2, string_index_size, blob_index_size, - result.tables[Param::TABLE].index_width(), + result.tables[MethodParam::TABLE].index_width(), ); unused_method_impl.set_columns( result.tables[TypeDef::TABLE].index_width(), @@ -442,7 +442,7 @@ impl File { 0, 0, ); - result.tables[Param::TABLE].set_columns(2, 2, string_index_size, 0, 0, 0); + result.tables[MethodParam::TABLE].set_columns(2, 2, string_index_size, 0, 0, 0); unused_property.set_columns(2, string_index_size, blob_index_size, 0, 0, 0); unused_property_map.set_columns( result.tables[TypeDef::TABLE].index_width(), @@ -476,7 +476,7 @@ impl File { result.tables[TypeDef::TABLE].set_data(&mut view); result.tables[Field::TABLE].set_data(&mut view); result.tables[MethodDef::TABLE].set_data(&mut view); - result.tables[Param::TABLE].set_data(&mut view); + result.tables[MethodParam::TABLE].set_data(&mut view); result.tables[InterfaceImpl::TABLE].set_data(&mut view); result.tables[MemberRef::TABLE].set_data(&mut view); result.tables[Constant::TABLE].set_data(&mut view);