From 16fa69e1853ccec350943288d0f4d284cce56871 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 7 Feb 2024 09:15:21 -0600 Subject: [PATCH 1/6] types --- .gitignore | 1 - crates/libs/bindgen/src/rdl/to_winmd.rs | 2 +- crates/libs/bindgen/src/winmd/from_reader.rs | 35 +++++- crates/libs/bindgen/src/winmd/writer/codes.rs | 104 +++++++++--------- crates/libs/bindgen/src/winmd/writer/mod.rs | 43 ++++---- .../libs/bindgen/src/winmd/writer/tables.rs | 60 ++++++++-- crates/libs/metadata/src/lib.rs | 1 + crates/libs/metadata/src/tables.rs | 10 ++ crates/tools/riddle/src/main.rs | 4 +- 9 files changed, 165 insertions(+), 95 deletions(-) diff --git a/.gitignore b/.gitignore index be7c0e6cfa..4c6fca839a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /.vscode /.vs /target -/temp *.lock *.winmd diff --git a/crates/libs/bindgen/src/rdl/to_winmd.rs b/crates/libs/bindgen/src/rdl/to_winmd.rs index efb2321168..12588134bb 100644 --- a/crates/libs/bindgen/src/rdl/to_winmd.rs +++ b/crates/libs/bindgen/src/rdl/to_winmd.rs @@ -70,7 +70,7 @@ fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, memb } writer.tables.TypeDef.push(winmd::TypeDef { - Extends: 0, + Extends: winmd::TypeDefOrRef::none(), FieldList: writer.tables.Field.len() as u32, MethodList: writer.tables.MethodDef.len() as u32, Flags: flags.0, diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index 5771568257..4a9810b51e 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -1,4 +1,5 @@ use super::*; +use metadata::HasAttributes; pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { let mut writer = Writer::new(output); @@ -22,7 +23,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let generics = &metadata::type_def_generics(def); - let extends = if let Some(extends) = def.extends() { writer.insert_type_ref(extends.namespace, extends.name) } else { 0 }; + let extends = if let Some(extends) = def.extends() { writer.insert_type_ref(extends.namespace, extends.name) } else { TypeDefOrRef::none() }; writer.tables.TypeDef.push(TypeDef { Extends: extends, @@ -33,11 +34,13 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap TypeNamespace: writer.strings.insert(def.namespace()), }); + let def_ref = writer.tables.TypeDef.len() as u32 - 1; + for generic in def.generics() { writer.tables.GenericParam.push(GenericParam { Number: generic.number(), // TODO: isn't this just going to be incremental? Flags: 0, - Owner: TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1).encode(), + Owner: TypeOrMethodDef::TypeDef(def_ref).encode(), Name: writer.strings.insert(generic.name()), }); } @@ -53,7 +56,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap rest => unimplemented!("{rest:?}"), }; - writer.tables.InterfaceImpl.push(InterfaceImpl { Class: writer.tables.TypeDef.len() as u32 - 1, Interface: reference }); + writer.tables.InterfaceImpl.push(InterfaceImpl { Class: def_ref, Interface: reference }); } // TODO: if the class is "Apis" then should we sort the fields (constants) and methods (functions) for stability @@ -85,6 +88,32 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap writer.tables.Param.push(Param { Flags: param.flags().0, Sequence: param.sequence(), Name: writer.strings.insert(param.name()) }); } } + + for attribute in def.attributes() { + let metadata::AttributeType::MemberRef(attribute_ctor) = attribute.ty(); + assert_eq!(attribute_ctor.name(), ".ctor"); + let metadata::MemberRefParent::TypeRef(attribute_type) = attribute_ctor.parent(); + + // TODO: here's the issue: this is alreayd a TypeRef - need to get the index and turn it into a MemberRefPArent instead + let attribute_type_ref = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()); + + let signature = attribute_ctor.signature(); + let return_type = winmd_type(&signature.return_type); + let param_types: Vec = signature.params.iter().map(winmd_type).collect(); + let signature = writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); + + // writer.tables.MemberRef.push(MemberRef { + // Class: MemberRefParent::TypeRef(attribute_type_ref).encode(), + // Name: writer.strings.insert(".ctor"), + // Signature: signature, + // }); + + // writer.tables.CustomAttribute.push(CustomAttribute { + // Parent: def_ref, + // Type: writer.tables.MemberRef.len() as u32 - 1, + // Value: 0, // constructor argument values blob + // }); + } } // TODO: In theory, `config` could instruct this function to balance the types across a number of winmd files diff --git a/crates/libs/bindgen/src/winmd/writer/codes.rs b/crates/libs/bindgen/src/winmd/writer/codes.rs index c5aa789e0a..611faf6884 100644 --- a/crates/libs/bindgen/src/winmd/writer/codes.rs +++ b/crates/libs/bindgen/src/winmd/writer/codes.rs @@ -1,71 +1,69 @@ #![allow(dead_code, clippy::enum_variant_names)] -/// A `ResolutionScope` is an index into a certain table indicating the scope in which a TypeRef can be resolved. -#[derive(Clone)] -pub enum ResolutionScope { - Module(u32), - ModuleRef(u32), - AssemblyRef(u32), - TypeRef(u32), +macro_rules! code { + ($name:ident($size:literal) $(($table:ident, $code:literal))+) => { + #[derive(Clone, Copy)] + pub enum $name { + $($table(u32),)* + } + impl $name { + pub fn encode(&self) -> u32 { + match self { + $(Self::$table(row) => (row.overflowing_add(1).0) << $size | $code,)* + } + } + } + }; } -impl ResolutionScope { - pub fn encode(&self) -> u32 { - match self { - Self::Module(row) => (row + 1) << 2, - Self::ModuleRef(row) => ((row + 1) << 2) + 1, - Self::AssemblyRef(row) => ((row + 1) << 2) + 2, - Self::TypeRef(row) => ((row + 1) << 2) + 3, - } - } + +code! { AttributeType(3) + (MemberRef, 3) } -/// A `TypeDefOrRef` is an index into a certain table used to locate a type definition. -#[derive(Clone)] -pub enum TypeDefOrRef { - TypeDef(u32), - TypeRef(u32), - TypeSpec(u32), +code! { HasAttribute(5) + (MethodDef, 0) + (Field, 1) + (TypeRef, 2) + (TypeDef, 3) + (Param, 4) + (InterfaceImpl, 5) + (MemberRef, 6) + (TypeSpec, 13) + (GenericParam, 19) } -impl TypeDefOrRef { - pub fn encode(&self) -> u32 { - match self { - Self::TypeDef(row) => (row + 1) << 2, - Self::TypeRef(row) => ((row + 1) << 2) + 1, - Self::TypeSpec(row) => ((row + 1) << 2) + 2, - } - } +code! { HasConstant(2) + (Field, 0) } -/// A `HasConstant` is an index into a certain table used to identify the parent of a row in the `Constant` table. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum HasConstant { - Field(u32), - Param(u32), - Property(u32), +code! { MemberForwarded(1) + (MethodDef, 1) } -impl HasConstant { - pub fn encode(&self) -> u32 { - match self { - Self::Field(row) => (row + 1) << 2, - Self::Param(row) => ((row + 1) << 2) + 1, - Self::Property(row) => ((row + 1) << 2) + 2, - } - } +code! { MemberRefParent(3) + (TypeRef, 1) } -/// A `TypeOrMethodDef` is an index into a certain table used to locate the owner of a generic parameter. -#[derive(Clone)] -pub enum TypeOrMethodDef { - TypeDef(u32), +code! { TypeDefOrRef(2) + (TypeDef, 0) + (TypeRef, 1) + (TypeSpec, 2) } -impl TypeOrMethodDef { - pub fn encode(&self) -> u32 { - match self { - Self::TypeDef(row) => (row + 1) << 1, - } +impl TypeDefOrRef { + pub fn none() -> Self { + TypeDefOrRef::TypeDef(u32::MAX) } } + +code! { TypeOrMethodDef(1) + (TypeDef, 0) +} + +code! { ResolutionScope(2) + (Module, 0) + (ModuleRef, 1) + (AssemblyRef, 2) + (TypeRef, 3) +} \ No newline at end of file diff --git a/crates/libs/bindgen/src/winmd/writer/mod.rs b/crates/libs/bindgen/src/winmd/writer/mod.rs index 7ac4a08d61..0efd77b539 100644 --- a/crates/libs/bindgen/src/winmd/writer/mod.rs +++ b/crates/libs/bindgen/src/winmd/writer/mod.rs @@ -19,10 +19,10 @@ pub struct Writer { pub blobs: Blobs, pub strings: Strings, pub tables: Tables, - pub scopes: HashMap, + pub scopes: HashMap, // TODO: is this faster than jsut using a single HashMap with a (String,String) key? - pub type_refs: HashMap>, - pub type_specs: HashMap, + pub type_refs: HashMap>, + pub type_specs: HashMap, } impl Writer { @@ -36,7 +36,7 @@ impl Writer { type_specs: Default::default(), }; - writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert(""), ..Default::default() }); + writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert(""), Flags: 0, TypeNamespace: 0, Extends: TypeDefOrRef::none(), FieldList: 0, MethodList: 0 }); let name = name.rsplit_once(&['/', '\\']).map_or(name, |(_, name)| name); @@ -88,7 +88,7 @@ impl Writer { self.blobs.insert(&blob) } - fn insert_scope(&mut self, namespace: &str) -> u32 { + fn insert_scope(&mut self, namespace: &str) -> ResolutionScope { if let Some(scope) = self.scopes.get(namespace) { *scope } else if namespace == "System" { @@ -97,8 +97,7 @@ impl Writer { MajorVersion: 4, PublicKeyOrToken: self.blobs.insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]), // TODO: comment on this ..Default::default() - })) - .encode(); + })); self.scopes.insert(namespace.to_string(), scope); scope } else { @@ -111,14 +110,13 @@ impl Writer { RevisionNumber: 0xFF, Flags: metadata::AssemblyFlags::WindowsRuntime.0, ..Default::default() - })) - .encode(); + })); self.scopes.insert(namespace.to_string(), scope); scope } } - pub fn insert_type_ref(&mut self, namespace: &str, name: &str) -> u32 { + pub fn insert_type_ref(&mut self, namespace: &str, name: &str) -> TypeDefOrRef { if let Some(key) = self.type_refs.get(namespace) { if let Some(reference) = key.get(name) { return *reference; @@ -127,12 +125,12 @@ impl Writer { let scope = self.insert_scope(namespace); - let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { TypeName: self.strings.insert(name), TypeNamespace: self.strings.insert(namespace), ResolutionScope: scope })).encode(); + let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { TypeName: self.strings.insert(name), TypeNamespace: self.strings.insert(namespace), ResolutionScope: scope })); self.type_refs.entry(namespace.to_string()).or_default().insert(name.to_string(), reference); reference } - pub fn insert_type_spec(&mut self, ty: Type) -> u32 { + pub fn insert_type_spec(&mut self, ty: Type) -> TypeDefOrRef { if let Some(key) = self.type_specs.get(&ty) { return *key; } @@ -141,8 +139,7 @@ impl Writer { self.type_blob(&ty, &mut blob); let signature = self.blobs.insert(&blob); - let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { Signature: signature })).encode(); - + let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { Signature: signature })); self.type_specs.insert(ty, reference); reference } @@ -169,12 +166,12 @@ impl Writer { Type::GUID => { let code = self.insert_type_ref("System", "Guid"); blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); } Type::HRESULT => { let code = self.insert_type_ref("Windows.Foundation", "HResult"); blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); } Type::TypeRef(ty) => { if !ty.generics.is_empty() { @@ -182,7 +179,7 @@ impl Writer { } let code = self.insert_type_ref(&ty.namespace, &ty.name); blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); if !ty.generics.is_empty() { usize_blob(ty.generics.len(), blob); @@ -195,26 +192,26 @@ impl Writer { Type::BSTR => { let code = self.insert_type_ref("Windows.Win32.Foundation", "BSTR"); blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); } Type::IUnknown => { let code = self.insert_type_ref("Windows.Win32.Foundation", "IUnknown"); blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); } Type::PCWSTR | Type::PWSTR => { let code = self.insert_type_ref("Windows.Win32.Foundation", "PWSTR"); blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); } Type::PCSTR | Type::PSTR => { let code = self.insert_type_ref("Windows.Win32.Foundation", "PSTR"); blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); } Type::ConstRef(ty) => { usize_blob(metadata::ELEMENT_TYPE_CMOD_OPT as usize, blob); - usize_blob(self.insert_type_ref("System.Runtime.CompilerServices", "IsConst") as usize, blob); + usize_blob(self.insert_type_ref("System.Runtime.CompilerServices", "IsConst").encode() as usize, blob); usize_blob(metadata::ELEMENT_TYPE_BYREF as usize, blob); self.type_blob(ty, blob); } @@ -237,7 +234,7 @@ impl Writer { Type::Type => { let code = self.insert_type_ref("System", "Type"); blob.push(metadata::ELEMENT_TYPE_CLASS); - usize_blob(code as usize, blob); + usize_blob(code.encode() as usize, blob); } Type::MutPtr(ty, pointers) | Type::ConstPtr(ty, pointers) => { for _ in 0..*pointers { diff --git a/crates/libs/bindgen/src/winmd/writer/tables.rs b/crates/libs/bindgen/src/winmd/writer/tables.rs index df31abd41c..c01de4c358 100644 --- a/crates/libs/bindgen/src/winmd/writer/tables.rs +++ b/crates/libs/bindgen/src/winmd/writer/tables.rs @@ -3,6 +3,9 @@ use super::Write; use super::*; +// TODO: make these columns strongly types + + #[derive(Default)] pub struct Tables { // TODO: use BTreeSet for tables that have a primary key, unless they are naturally sorted. @@ -97,10 +100,9 @@ pub struct ImplMap { pub ImportScope: u32, } -#[derive(Default)] pub struct InterfaceImpl { pub Class: u32, - pub Interface: u32, + pub Interface: TypeDefOrRef, } #[derive(Default)] @@ -154,19 +156,17 @@ pub struct Property { pub Type: u32, } -#[derive(Default)] pub struct TypeDef { pub Flags: u32, pub TypeName: u32, pub TypeNamespace: u32, - pub Extends: u32, + pub Extends: TypeDefOrRef, pub FieldList: u32, pub MethodList: u32, } -#[derive(Default)] pub struct TypeRef { - pub ResolutionScope: u32, + pub ResolutionScope: ResolutionScope, pub TypeName: u32, pub TypeNamespace: u32, } @@ -183,12 +183,36 @@ impl Tables { } let resolution_scope = metadata::coded_index_size(&[self.Module.len(), self.ModuleRef.len(), self.AssemblyRef.len(), self.TypeRef.len()]); - let type_def_or_ref = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()]); - let has_constant = metadata::coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]); - let type_or_method_def = metadata::coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]); + let member_ref_parent = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.ModuleRef.len(), self.MethodDef.len(), self.TypeSpec.len()]); + let custom_attribute_type = metadata::coded_index_size(&[self.MethodDef.len(), self.MemberRef.len(), 0, 0, 0]); + + let has_custom_attribute = 0; + // let has_custom_attribute = metadata::coded_index_size(&[ + // tables[MethodDef::TABLE].len, + // tables[Field::TABLE].len, + // tables[TypeRef::TABLE].len, + // tables[TypeDef::TABLE].len, + // tables[Param::TABLE].len, + // tables[InterfaceImpl::TABLE].len, + // tables[MemberRef::TABLE].len, + // tables[Module::TABLE].len, + // unused_property.len, + // unused_event.len, + // unused_standalone_sig.len, + // tables[ModuleRef::TABLE].len, + // tables[TypeSpec::TABLE].len, + // unused_assembly.len, + // tables[AssemblyRef::TABLE].len, + // unused_file.len, + // unused_exported_type.len, + // unused_manifest_resource.len, + // tables[GenericParam::TABLE].len, + // unused_generic_param_constraint.len, + // unused_method_spec.len, + // ]); let valid_tables: u64 = 1 << 0 | // Module 1 << 0x01 | // TypeRef @@ -254,7 +278,7 @@ impl Tables { } for x in self.TypeRef { - buffer.write_code(x.ResolutionScope, resolution_scope); + buffer.write_code(x.ResolutionScope.encode(), resolution_scope); buffer.write_u32(x.TypeName); buffer.write_u32(x.TypeNamespace); } @@ -263,7 +287,7 @@ impl Tables { buffer.write_u32(x.Flags); buffer.write_u32(x.TypeName); buffer.write_u32(x.TypeNamespace); - buffer.write_code(x.Extends, type_def_or_ref); + buffer.write_code(x.Extends.encode(), type_def_or_ref); buffer.write_index(x.FieldList, self.Field.len()); buffer.write_index(x.MethodList, self.MethodDef.len()); } @@ -291,7 +315,13 @@ impl Tables { for x in self.InterfaceImpl { buffer.write_index(x.Class, self.TypeDef.len()); - buffer.write_code(x.Interface, type_def_or_ref); + buffer.write_code(x.Interface.encode(), type_def_or_ref); + } + + for x in self.MemberRef { + buffer.write_code(x.Class, member_ref_parent); + buffer.write_u32(x.Name); + buffer.write_u32(x.Signature); } for x in self.Constant { @@ -300,6 +330,12 @@ impl Tables { buffer.write_u32(x.Value); } + for x in self.CustomAttribute { + buffer.write_code(x.Parent, has_custom_attribute); + buffer.write_code(x.Type, custom_attribute_type); + buffer.write_u32(x.Value); + } + for x in self.TypeSpec { buffer.write_u32(x.Signature); } diff --git a/crates/libs/metadata/src/lib.rs b/crates/libs/metadata/src/lib.rs index 1b3d959cc1..870be4c649 100644 --- a/crates/libs/metadata/src/lib.rs +++ b/crates/libs/metadata/src/lib.rs @@ -97,6 +97,7 @@ pub enum Value { EnumDef(TypeDef, Box), } +#[derive(Debug)] pub struct MethodDefSig { pub call_flags: MethodCallAttributes, pub return_type: Type, diff --git a/crates/libs/metadata/src/tables.rs b/crates/libs/metadata/src/tables.rs index d7e3ad6086..662f1f862a 100644 --- a/crates/libs/metadata/src/tables.rs +++ b/crates/libs/metadata/src/tables.rs @@ -219,6 +219,16 @@ impl MemberRef { pub fn name(&self) -> &'static str { self.str(1) } + + pub fn signature(&self) -> MethodDefSig { + let reader = self.reader(); + let mut blob = self.blob(2); + let call_flags = MethodCallAttributes(blob.read_usize() as u8); + let params = blob.read_usize(); + let return_type = reader.type_from_blob(&mut blob, None, &[]); + + MethodDefSig { call_flags, return_type, params: (0..params).map(|_| reader.type_from_blob(&mut blob, None, &[])).collect() } + } } impl MethodDef { diff --git a/crates/tools/riddle/src/main.rs b/crates/tools/riddle/src/main.rs index 1794dfa95f..65185952a0 100644 --- a/crates/tools/riddle/src/main.rs +++ b/crates/tools/riddle/src/main.rs @@ -16,9 +16,9 @@ Options: ); } else { match windows_bindgen::bindgen(args) { - Ok(ok) => println!("{}", ok), + Ok(ok) => println!("{ok}"), Err(error) => { - eprintln!("{}", error); + eprintln!("{error}"); std::process::exit(1); } } From b9748ddc44d88bb97f87d4029c022cecb03cf07e Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 7 Feb 2024 13:57:34 -0600 Subject: [PATCH 2/6] close --- crates/libs/bindgen/src/rust/interfaces.rs | 7 ++- crates/libs/bindgen/src/winmd/from_reader.rs | 55 +++++++++++++---- crates/libs/bindgen/src/winmd/writer/codes.rs | 1 + crates/libs/bindgen/src/winmd/writer/mod.rs | 3 +- .../libs/bindgen/src/winmd/writer/tables.rs | 61 +++++++++---------- crates/libs/metadata/src/tables.rs | 9 ++- crates/libs/metadata/src/type_name.rs | 4 ++ test.rs | 35 +++++++++++ 8 files changed, 126 insertions(+), 49 deletions(-) create mode 100644 test.rs diff --git a/crates/libs/bindgen/src/rust/interfaces.rs b/crates/libs/bindgen/src/rust/interfaces.rs index 0f6ae64246..40db4a4577 100644 --- a/crates/libs/bindgen/src/rust/interfaces.rs +++ b/crates/libs/bindgen/src/rust/interfaces.rs @@ -1,5 +1,5 @@ use super::*; - +use windows_metadata::HasAttributes; pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { if writer.sys { quote! {} @@ -21,6 +21,11 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let vtables = metadata::type_def_vtables(def); let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::IUnknown)); + println!("attributes {}", def.attributes().count()); + for attribute in def.attributes() { + println!("attribute {}", attribute.name()); + } + let mut tokens = quote! {}; if has_unknown_base { diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index 4a9810b51e..a13d2839aa 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -95,24 +95,55 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let metadata::MemberRefParent::TypeRef(attribute_type) = attribute_ctor.parent(); // TODO: here's the issue: this is alreayd a TypeRef - need to get the index and turn it into a MemberRefPArent instead - let attribute_type_ref = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()); + let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) { + MemberRefParent::TypeRef(type_ref) + } else { + panic!() + }; let signature = attribute_ctor.signature(); let return_type = winmd_type(&signature.return_type); let param_types: Vec = signature.params.iter().map(winmd_type).collect(); let signature = writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); - // writer.tables.MemberRef.push(MemberRef { - // Class: MemberRefParent::TypeRef(attribute_type_ref).encode(), - // Name: writer.strings.insert(".ctor"), - // Signature: signature, - // }); - - // writer.tables.CustomAttribute.push(CustomAttribute { - // Parent: def_ref, - // Type: writer.tables.MemberRef.len() as u32 - 1, - // Value: 0, // constructor argument values blob - // }); + writer.tables.MemberRef.push(MemberRef { + Class: attribute_type_ref, + Name: writer.strings.insert(".ctor"), + Signature: signature, + }); + + // // TODO debug this with windows-metadata + let mut values = 1u16.to_le_bytes().to_vec(); // prolog + let args = attribute.args(); + + for (index, (name, value)) in args.iter().enumerate() { + match value { + metadata::Value::Bool(value) => if *value { values.push(1) } else { values.push(0 )}, + metadata::Value::TypeName(value) => { + let value = value.to_string(); + usize_blob(value.len(), &mut values); + values.extend_from_slice(value.as_bytes()); + } + metadata::Value::U32(value) => values.extend_from_slice(&value.to_le_bytes()), + metadata::Value::U16(value) => values.extend_from_slice(&value.to_le_bytes()), + metadata::Value::U8(value) => values.extend_from_slice(&value.to_le_bytes()), + rest => unimplemented!("{rest:?}"), + } + + if !name.is_empty() { + let named_arg_count: u16 = (args.len() - index) as u16; + values.extend_from_slice(&named_arg_count.to_le_bytes()); + break; + } + } + + let values = writer.blobs.insert(&values); + + writer.tables.CustomAttribute.push(CustomAttribute { + Parent: HasAttribute::TypeDef(def_ref), + Type: AttributeType::MemberRef(writer.tables.MemberRef.len() as u32 - 1), + Value: values + }); } } diff --git a/crates/libs/bindgen/src/winmd/writer/codes.rs b/crates/libs/bindgen/src/winmd/writer/codes.rs index 611faf6884..e1fd2ec5c8 100644 --- a/crates/libs/bindgen/src/winmd/writer/codes.rs +++ b/crates/libs/bindgen/src/winmd/writer/codes.rs @@ -21,6 +21,7 @@ code! { AttributeType(3) (MemberRef, 3) } +// TODO: needs to be called HasCustomAttribute code! { HasAttribute(5) (MethodDef, 0) (Field, 1) diff --git a/crates/libs/bindgen/src/winmd/writer/mod.rs b/crates/libs/bindgen/src/winmd/writer/mod.rs index 0efd77b539..3932dddd7a 100644 --- a/crates/libs/bindgen/src/winmd/writer/mod.rs +++ b/crates/libs/bindgen/src/winmd/writer/mod.rs @@ -255,7 +255,8 @@ fn round(size: usize, round: usize) -> usize { (size + round) & !round } -fn usize_blob(value: usize, blob: &mut Vec) { +// TODO: need a Blob type for writing +pub fn usize_blob(value: usize, blob: &mut Vec) { // See II.23.2 in ECMA-335 assert!(value < 0x20000000); diff --git a/crates/libs/bindgen/src/winmd/writer/tables.rs b/crates/libs/bindgen/src/winmd/writer/tables.rs index c01de4c358..1c3ce5688e 100644 --- a/crates/libs/bindgen/src/winmd/writer/tables.rs +++ b/crates/libs/bindgen/src/winmd/writer/tables.rs @@ -70,10 +70,9 @@ pub struct Constant { pub Value: u32, } -#[derive(Default)] pub struct CustomAttribute { - pub Parent: u32, - pub Type: u32, + pub Parent: HasAttribute, + pub Type: AttributeType, pub Value: u32, } @@ -105,9 +104,8 @@ pub struct InterfaceImpl { pub Interface: TypeDefOrRef, } -#[derive(Default)] pub struct MemberRef { - pub Class: u32, + pub Class: MemberRefParent, pub Name: u32, pub Signature: u32, } @@ -189,30 +187,29 @@ impl Tables { let member_ref_parent = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.ModuleRef.len(), self.MethodDef.len(), self.TypeSpec.len()]); let custom_attribute_type = metadata::coded_index_size(&[self.MethodDef.len(), self.MemberRef.len(), 0, 0, 0]); - let has_custom_attribute = 0; - // let has_custom_attribute = metadata::coded_index_size(&[ - // tables[MethodDef::TABLE].len, - // tables[Field::TABLE].len, - // tables[TypeRef::TABLE].len, - // tables[TypeDef::TABLE].len, - // tables[Param::TABLE].len, - // tables[InterfaceImpl::TABLE].len, - // tables[MemberRef::TABLE].len, - // tables[Module::TABLE].len, - // unused_property.len, - // unused_event.len, - // unused_standalone_sig.len, - // tables[ModuleRef::TABLE].len, - // tables[TypeSpec::TABLE].len, - // unused_assembly.len, - // tables[AssemblyRef::TABLE].len, - // unused_file.len, - // unused_exported_type.len, - // unused_manifest_resource.len, - // tables[GenericParam::TABLE].len, - // unused_generic_param_constraint.len, - // unused_method_spec.len, - // ]); + let has_custom_attribute = metadata::coded_index_size(&[ + self.MethodDef.len(), + self.Field.len(), + self.TypeRef.len(), + self.TypeDef.len(), + self.Param.len(), + self.InterfaceImpl.len(), + self.MemberRef.len(), + self.Module.len(), + 0, + 0, + 0, + self.ModuleRef.len(), + self.TypeSpec.len(), + 0, + self.AssemblyRef.len(), + 0, + 0, + 0, + self.GenericParam.len(), + 0, + 0, + ]); let valid_tables: u64 = 1 << 0 | // Module 1 << 0x01 | // TypeRef @@ -319,7 +316,7 @@ impl Tables { } for x in self.MemberRef { - buffer.write_code(x.Class, member_ref_parent); + buffer.write_code(x.Class.encode(), member_ref_parent); buffer.write_u32(x.Name); buffer.write_u32(x.Signature); } @@ -331,8 +328,8 @@ impl Tables { } for x in self.CustomAttribute { - buffer.write_code(x.Parent, has_custom_attribute); - buffer.write_code(x.Type, custom_attribute_type); + buffer.write_code(x.Parent.encode(), has_custom_attribute); + buffer.write_code(x.Type.encode(), custom_attribute_type); buffer.write_u32(x.Value); } diff --git a/crates/libs/metadata/src/tables.rs b/crates/libs/metadata/src/tables.rs index 662f1f862a..15c1bf745b 100644 --- a/crates/libs/metadata/src/tables.rs +++ b/crates/libs/metadata/src/tables.rs @@ -63,10 +63,13 @@ impl Attribute { let AttributeType::MemberRef(member) = self.ty(); let mut sig = member.blob(2); let mut values = self.blob(2); - let _prolog = values.read_u16(); - let _this_and_gen_param_count = sig.read_usize(); + let prolog = values.read_u16(); + std::debug_assert_eq!(prolog, 1); + let this_and_gen_param_count = sig.read_usize(); + std::debug_assert_eq!(this_and_gen_param_count, 32); let fixed_arg_count = sig.read_usize(); - let _ret_type = sig.read_usize(); + let ret_type = sig.read_usize(); + std::debug_assert_eq!(ret_type, 1); let mut args = Vec::with_capacity(fixed_arg_count); let reader = self.reader(); diff --git a/crates/libs/metadata/src/type_name.rs b/crates/libs/metadata/src/type_name.rs index de0fce9258..13a578df7e 100644 --- a/crates/libs/metadata/src/type_name.rs +++ b/crates/libs/metadata/src/type_name.rs @@ -62,6 +62,10 @@ impl TypeName { let index = full_name.rfind('.').expect("Expected full name separated with `.`"); Self::new(&full_name[0..index], &full_name[index + 1..]) } + + pub fn to_string(&self) -> String { + format!("{}.{}", self.namespace, self.name) + } } impl std::fmt::Display for TypeName { diff --git a/test.rs b/test.rs new file mode 100644 index 0000000000..556720ac62 --- /dev/null +++ b/test.rs @@ -0,0 +1,35 @@ +// Bindings generated by `windows-bindgen` 0.52.0 + +#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] +pub mod Foundation { + ::windows_core::imp::com_interface!(IStringable, IStringable_Vtbl, 0); + ::windows_core::imp::interface_hierarchy!(IStringable, ::windows_core::IUnknown, ::windows_core::IInspectable); + impl IStringable { + pub fn ToString(&self) -> ::windows_core::Result<::windows_core::HSTRING> { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).ToString)(::windows_core::Interface::as_raw(this), &mut result__).from_abi(result__) + } + } + } + impl ::windows_core::RuntimeType for IStringable { + const SIGNATURE: ::windows_core::imp::ConstBuffer = ::windows_core::imp::ConstBuffer::for_interface::(); + } + #[repr(C)] + #[doc(hidden)] + pub struct IStringable_Vtbl { + pub base__: ::windows_core::IInspectable_Vtbl, + pub ToString: unsafe extern "system" fn(*mut ::core::ffi::c_void, *mut ::std::mem::MaybeUninit<::windows_core::HSTRING>) -> ::windows_core::HRESULT, + } + impl ::core::convert::From<::core::time::Duration> for TimeSpan { + fn from(value: ::core::time::Duration) -> Self { + Self { Duration: (value.as_nanos() / 100) as i64 } + } + } + impl ::core::convert::From for ::core::time::Duration { + fn from(value: TimeSpan) -> Self { + ::core::time::Duration::from_nanos((value.Duration * 100) as u64) + } + } +} From d9a9ae4722c4fb9db9282f41dd5f95717ae59d0b Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 7 Feb 2024 14:11:24 -0600 Subject: [PATCH 3/6] works --- crates/libs/bindgen/src/rust/interfaces.rs | 7 +--- crates/libs/bindgen/src/winmd/from_reader.rs | 12 ++++--- test.rs | 35 -------------------- 3 files changed, 9 insertions(+), 45 deletions(-) delete mode 100644 test.rs diff --git a/crates/libs/bindgen/src/rust/interfaces.rs b/crates/libs/bindgen/src/rust/interfaces.rs index 40db4a4577..0f6ae64246 100644 --- a/crates/libs/bindgen/src/rust/interfaces.rs +++ b/crates/libs/bindgen/src/rust/interfaces.rs @@ -1,5 +1,5 @@ use super::*; -use windows_metadata::HasAttributes; + pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { if writer.sys { quote! {} @@ -21,11 +21,6 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let vtables = metadata::type_def_vtables(def); let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::IUnknown)); - println!("attributes {}", def.attributes().count()); - for attribute in def.attributes() { - println!("attribute {}", attribute.name()); - } - let mut tokens = quote! {}; if has_unknown_base { diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index a13d2839aa..8f58df6209 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -94,7 +94,6 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap assert_eq!(attribute_ctor.name(), ".ctor"); let metadata::MemberRefParent::TypeRef(attribute_type) = attribute_ctor.parent(); - // TODO: here's the issue: this is alreayd a TypeRef - need to get the index and turn it into a MemberRefPArent instead let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) { MemberRefParent::TypeRef(type_ref) } else { @@ -112,9 +111,9 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap Signature: signature, }); - // // TODO debug this with windows-metadata let mut values = 1u16.to_le_bytes().to_vec(); // prolog let args = attribute.args(); + let mut named_arg_count = false; for (index, (name, value)) in args.iter().enumerate() { match value { @@ -130,13 +129,18 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap rest => unimplemented!("{rest:?}"), } - if !name.is_empty() { - let named_arg_count: u16 = (args.len() - index) as u16; + if !named_arg_count && !name.is_empty() { + named_arg_count = true; + let named_arg_count = (args.len() - index) as u16; values.extend_from_slice(&named_arg_count.to_le_bytes()); break; } } + if !named_arg_count { + values.extend_from_slice(&0u16.to_le_bytes()); + } + let values = writer.blobs.insert(&values); writer.tables.CustomAttribute.push(CustomAttribute { diff --git a/test.rs b/test.rs deleted file mode 100644 index 556720ac62..0000000000 --- a/test.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Bindings generated by `windows-bindgen` 0.52.0 - -#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] -pub mod Foundation { - ::windows_core::imp::com_interface!(IStringable, IStringable_Vtbl, 0); - ::windows_core::imp::interface_hierarchy!(IStringable, ::windows_core::IUnknown, ::windows_core::IInspectable); - impl IStringable { - pub fn ToString(&self) -> ::windows_core::Result<::windows_core::HSTRING> { - let this = self; - unsafe { - let mut result__ = ::std::mem::zeroed(); - (::windows_core::Interface::vtable(this).ToString)(::windows_core::Interface::as_raw(this), &mut result__).from_abi(result__) - } - } - } - impl ::windows_core::RuntimeType for IStringable { - const SIGNATURE: ::windows_core::imp::ConstBuffer = ::windows_core::imp::ConstBuffer::for_interface::(); - } - #[repr(C)] - #[doc(hidden)] - pub struct IStringable_Vtbl { - pub base__: ::windows_core::IInspectable_Vtbl, - pub ToString: unsafe extern "system" fn(*mut ::core::ffi::c_void, *mut ::std::mem::MaybeUninit<::windows_core::HSTRING>) -> ::windows_core::HRESULT, - } - impl ::core::convert::From<::core::time::Duration> for TimeSpan { - fn from(value: ::core::time::Duration) -> Self { - Self { Duration: (value.as_nanos() / 100) as i64 } - } - } - impl ::core::convert::From for ::core::time::Duration { - fn from(value: TimeSpan) -> Self { - ::core::time::Duration::from_nanos((value.Duration * 100) as u64) - } - } -} From c1fddff4ff7ba626d6d2b4272c6f7b4fa69a72d2 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 8 Feb 2024 09:19:59 -0600 Subject: [PATCH 4/6] foundation --- crates/libs/bindgen/src/winmd/from_reader.rs | 37 +++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index 8f58df6209..826d134f09 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -116,18 +116,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let mut named_arg_count = false; for (index, (name, value)) in args.iter().enumerate() { - match value { - metadata::Value::Bool(value) => if *value { values.push(1) } else { values.push(0 )}, - metadata::Value::TypeName(value) => { - let value = value.to_string(); - usize_blob(value.len(), &mut values); - values.extend_from_slice(value.as_bytes()); - } - metadata::Value::U32(value) => values.extend_from_slice(&value.to_le_bytes()), - metadata::Value::U16(value) => values.extend_from_slice(&value.to_le_bytes()), - metadata::Value::U8(value) => values.extend_from_slice(&value.to_le_bytes()), - rest => unimplemented!("{rest:?}"), - } + value_blob(value, &mut values); if !named_arg_count && !name.is_empty() { named_arg_count = true; @@ -156,6 +145,30 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap write_to_file(output, writer.into_stream()).map_err(|err| err.with_path(output)) } +// TODO: need a Blob type for writing +fn value_blob(value: &metadata::Value, blob: &mut Vec) { + match value { + metadata::Value::Bool(value) => if *value { blob.push(1) } else { blob.push(0 )}, + metadata::Value::U32(value) => blob.extend_from_slice(&value.to_le_bytes()), + metadata::Value::I32(value) => blob.extend_from_slice(&value.to_le_bytes()), + metadata::Value::U16(value) => blob.extend_from_slice(&value.to_le_bytes()), + metadata::Value::U8(value) => blob.extend_from_slice(&value.to_le_bytes()), + metadata::Value::EnumDef(_def, value) => value_blob(value, blob), + + metadata::Value::TypeName(value) => { + let value = value.to_string(); + usize_blob(value.len(), blob); + blob.extend_from_slice(value.as_bytes()); + } + metadata::Value::String(value) => { + usize_blob(value.len(), blob); + blob.extend_from_slice(value.as_bytes()); + } + rest => unimplemented!("{rest:?}"), + } + +} + // TODO: keep the basic type conversion fn winmd_type(ty: &metadata::Type) -> Type { match ty { From ea5f8bb6a67b5031a83b49f8a17462ad483bc143 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 13 Feb 2024 09:34:10 -0600 Subject: [PATCH 5/6] constants --- crates/libs/bindgen/src/rdl/to_winmd.rs | 2 +- crates/libs/bindgen/src/winmd/from_reader.rs | 12 ++++++++++-- crates/libs/bindgen/src/winmd/writer/tables.rs | 10 ++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/libs/bindgen/src/rdl/to_winmd.rs b/crates/libs/bindgen/src/rdl/to_winmd.rs index 12588134bb..2cdb6bab16 100644 --- a/crates/libs/bindgen/src/rdl/to_winmd.rs +++ b/crates/libs/bindgen/src/rdl/to_winmd.rs @@ -82,7 +82,7 @@ fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, memb writer.tables.GenericParam.push(writer::GenericParam { Number: number as u16, Flags: 0, - Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1).encode(), + Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1), Name: writer.strings.insert(generic), }); } diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index 826d134f09..3bbeea503a 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -1,5 +1,5 @@ use super::*; -use metadata::HasAttributes; +use metadata::{HasAttributes, AsRow}; pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { let mut writer = Writer::new(output); @@ -40,7 +40,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap writer.tables.GenericParam.push(GenericParam { Number: generic.number(), // TODO: isn't this just going to be incremental? Flags: 0, - Owner: TypeOrMethodDef::TypeDef(def_ref).encode(), + Owner: TypeOrMethodDef::TypeDef(def_ref), Name: writer.strings.insert(generic.name()), }); } @@ -66,6 +66,14 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let signature = writer.insert_field_sig(&ty); writer.tables.Field.push(Field { Flags: field.flags().0, Name: writer.strings.insert(field.name()), Signature: signature }); + + if let Some(constant) = field.constant() { + writer.tables.Constant.push(Constant { + Type: constant.usize(0) as u16, + Parent: HasConstant::Field(writer.tables.Field.len() as u32 -1), + Value: writer.blobs.insert(&constant.blob(2)), + }) + } } for method in def.methods() { diff --git a/crates/libs/bindgen/src/winmd/writer/tables.rs b/crates/libs/bindgen/src/winmd/writer/tables.rs index 1c3ce5688e..51a64563d4 100644 --- a/crates/libs/bindgen/src/winmd/writer/tables.rs +++ b/crates/libs/bindgen/src/winmd/writer/tables.rs @@ -63,10 +63,9 @@ pub struct ClassLayout { pub Parent: u32, } -#[derive(Default)] pub struct Constant { pub Type: u16, - pub Parent: u32, + pub Parent: HasConstant, pub Value: u32, } @@ -83,11 +82,10 @@ pub struct Field { pub Signature: u32, } -#[derive(Default)] pub struct GenericParam { pub Number: u16, pub Flags: u16, - pub Owner: u32, + pub Owner: TypeOrMethodDef, pub Name: u32, } @@ -323,7 +321,7 @@ impl Tables { for x in self.Constant { buffer.write_u16(x.Type); - buffer.write_code(x.Parent, has_constant); + buffer.write_code(x.Parent.encode(), has_constant); buffer.write_u32(x.Value); } @@ -364,7 +362,7 @@ impl Tables { for x in self.GenericParam { buffer.write_u16(x.Number); buffer.write_u16(x.Flags); - buffer.write_code(x.Owner, type_or_method_def); + buffer.write_code(x.Owner.encode(), type_or_method_def); buffer.write_u32(x.Name); } From e000d30fda1560623e2ae74a271438951efffb74 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 13 Feb 2024 09:41:40 -0600 Subject: [PATCH 6/6] fmt --- crates/libs/bindgen/src/winmd/from_reader.rs | 39 +++++++------------ crates/libs/bindgen/src/winmd/writer/codes.rs | 3 +- crates/libs/bindgen/src/winmd/writer/mod.rs | 2 +- .../libs/bindgen/src/winmd/writer/tables.rs | 28 +------------ crates/libs/metadata/src/type_name.rs | 4 -- 5 files changed, 17 insertions(+), 59 deletions(-) diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index 3bbeea503a..534c35ecc3 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -1,5 +1,5 @@ use super::*; -use metadata::{HasAttributes, AsRow}; +use metadata::{AsRow, HasAttributes}; pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { let mut writer = Writer::new(output); @@ -68,11 +68,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap writer.tables.Field.push(Field { Flags: field.flags().0, Name: writer.strings.insert(field.name()), Signature: signature }); if let Some(constant) = field.constant() { - writer.tables.Constant.push(Constant { - Type: constant.usize(0) as u16, - Parent: HasConstant::Field(writer.tables.Field.len() as u32 -1), - Value: writer.blobs.insert(&constant.blob(2)), - }) + writer.tables.Constant.push(Constant { Type: constant.usize(0) as u16, Parent: HasConstant::Field(writer.tables.Field.len() as u32 - 1), Value: writer.blobs.insert(&constant.blob(2)) }) } } @@ -102,22 +98,14 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap assert_eq!(attribute_ctor.name(), ".ctor"); let metadata::MemberRefParent::TypeRef(attribute_type) = attribute_ctor.parent(); - let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) { - MemberRefParent::TypeRef(type_ref) - } else { - panic!() - }; + let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) { MemberRefParent::TypeRef(type_ref) } else { panic!() }; let signature = attribute_ctor.signature(); let return_type = winmd_type(&signature.return_type); let param_types: Vec = signature.params.iter().map(winmd_type).collect(); let signature = writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); - - writer.tables.MemberRef.push(MemberRef { - Class: attribute_type_ref, - Name: writer.strings.insert(".ctor"), - Signature: signature, - }); + + writer.tables.MemberRef.push(MemberRef { Class: attribute_type_ref, Name: writer.strings.insert(".ctor"), Signature: signature }); let mut values = 1u16.to_le_bytes().to_vec(); // prolog let args = attribute.args(); @@ -140,11 +128,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap let values = writer.blobs.insert(&values); - writer.tables.CustomAttribute.push(CustomAttribute { - Parent: HasAttribute::TypeDef(def_ref), - Type: AttributeType::MemberRef(writer.tables.MemberRef.len() as u32 - 1), - Value: values - }); + writer.tables.CustomAttribute.push(CustomAttribute { Parent: HasAttribute::TypeDef(def_ref), Type: AttributeType::MemberRef(writer.tables.MemberRef.len() as u32 - 1), Value: values }); } } @@ -156,13 +140,19 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap // TODO: need a Blob type for writing fn value_blob(value: &metadata::Value, blob: &mut Vec) { match value { - metadata::Value::Bool(value) => if *value { blob.push(1) } else { blob.push(0 )}, + metadata::Value::Bool(value) => { + if *value { + blob.push(1) + } else { + blob.push(0) + } + } metadata::Value::U32(value) => blob.extend_from_slice(&value.to_le_bytes()), metadata::Value::I32(value) => blob.extend_from_slice(&value.to_le_bytes()), metadata::Value::U16(value) => blob.extend_from_slice(&value.to_le_bytes()), metadata::Value::U8(value) => blob.extend_from_slice(&value.to_le_bytes()), metadata::Value::EnumDef(_def, value) => value_blob(value, blob), - + metadata::Value::TypeName(value) => { let value = value.to_string(); usize_blob(value.len(), blob); @@ -174,7 +164,6 @@ fn value_blob(value: &metadata::Value, blob: &mut Vec) { } rest => unimplemented!("{rest:?}"), } - } // TODO: keep the basic type conversion diff --git a/crates/libs/bindgen/src/winmd/writer/codes.rs b/crates/libs/bindgen/src/winmd/writer/codes.rs index e1fd2ec5c8..16e2565c52 100644 --- a/crates/libs/bindgen/src/winmd/writer/codes.rs +++ b/crates/libs/bindgen/src/winmd/writer/codes.rs @@ -16,7 +16,6 @@ macro_rules! code { }; } - code! { AttributeType(3) (MemberRef, 3) } @@ -67,4 +66,4 @@ code! { ResolutionScope(2) (ModuleRef, 1) (AssemblyRef, 2) (TypeRef, 3) -} \ No newline at end of file +} diff --git a/crates/libs/bindgen/src/winmd/writer/mod.rs b/crates/libs/bindgen/src/winmd/writer/mod.rs index 3932dddd7a..1ad0086db3 100644 --- a/crates/libs/bindgen/src/winmd/writer/mod.rs +++ b/crates/libs/bindgen/src/winmd/writer/mod.rs @@ -36,7 +36,7 @@ impl Writer { type_specs: Default::default(), }; - writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert(""), Flags: 0, TypeNamespace: 0, Extends: TypeDefOrRef::none(), FieldList: 0, MethodList: 0 }); + writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert(""), Flags: 0, TypeNamespace: 0, Extends: TypeDefOrRef::none(), FieldList: 0, MethodList: 0 }); let name = name.rsplit_once(&['/', '\\']).map_or(name, |(_, name)| name); diff --git a/crates/libs/bindgen/src/winmd/writer/tables.rs b/crates/libs/bindgen/src/winmd/writer/tables.rs index 51a64563d4..474f9cce8d 100644 --- a/crates/libs/bindgen/src/winmd/writer/tables.rs +++ b/crates/libs/bindgen/src/winmd/writer/tables.rs @@ -3,9 +3,6 @@ use super::Write; use super::*; -// TODO: make these columns strongly types - - #[derive(Default)] pub struct Tables { // TODO: use BTreeSet for tables that have a primary key, unless they are naturally sorted. @@ -184,30 +181,7 @@ impl Tables { let type_or_method_def = metadata::coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]); let member_ref_parent = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.ModuleRef.len(), self.MethodDef.len(), self.TypeSpec.len()]); let custom_attribute_type = metadata::coded_index_size(&[self.MethodDef.len(), self.MemberRef.len(), 0, 0, 0]); - - let has_custom_attribute = metadata::coded_index_size(&[ - self.MethodDef.len(), - self.Field.len(), - self.TypeRef.len(), - self.TypeDef.len(), - self.Param.len(), - self.InterfaceImpl.len(), - self.MemberRef.len(), - self.Module.len(), - 0, - 0, - 0, - self.ModuleRef.len(), - self.TypeSpec.len(), - 0, - self.AssemblyRef.len(), - 0, - 0, - 0, - self.GenericParam.len(), - 0, - 0, - ]); + let has_custom_attribute = metadata::coded_index_size(&[self.MethodDef.len(), self.Field.len(), self.TypeRef.len(), self.TypeDef.len(), self.Param.len(), self.InterfaceImpl.len(), self.MemberRef.len(), self.Module.len(), 0, 0, 0, self.ModuleRef.len(), self.TypeSpec.len(), 0, self.AssemblyRef.len(), 0, 0, 0, self.GenericParam.len(), 0, 0]); let valid_tables: u64 = 1 << 0 | // Module 1 << 0x01 | // TypeRef diff --git a/crates/libs/metadata/src/type_name.rs b/crates/libs/metadata/src/type_name.rs index 13a578df7e..de0fce9258 100644 --- a/crates/libs/metadata/src/type_name.rs +++ b/crates/libs/metadata/src/type_name.rs @@ -62,10 +62,6 @@ impl TypeName { let index = full_name.rfind('.').expect("Expected full name separated with `.`"); Self::new(&full_name[0..index], &full_name[index + 1..]) } - - pub fn to_string(&self) -> String { - format!("{}.{}", self.namespace, self.name) - } } impl std::fmt::Display for TypeName {