From a036ce60502b5fa3b1af13cd898bdd97d39ad984 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 14 May 2024 13:20:00 -0500 Subject: [PATCH] Type name deferral in `windows-metadata` and `windows-bindgen` (#3039) --- crates/libs/bindgen/src/lib.rs | 2 - crates/libs/bindgen/src/metadata.rs | 36 ++++++++--------- crates/libs/bindgen/src/rdl/from_reader.rs | 22 +++++----- crates/libs/bindgen/src/rust/constants.rs | 12 +++--- crates/libs/bindgen/src/rust/implements.rs | 6 +-- crates/libs/bindgen/src/rust/interfaces.rs | 4 +- crates/libs/bindgen/src/rust/mod.rs | 2 +- crates/libs/bindgen/src/rust/standalone.rs | 30 +++++++------- crates/libs/bindgen/src/rust/structs.rs | 2 +- crates/libs/bindgen/src/rust/writer.rs | 36 ++++++++--------- crates/libs/bindgen/src/winmd/from_reader.rs | 20 +++++----- crates/libs/bindgen/src/winmd/mod.rs | 2 - crates/libs/bindgen/src/winmd/verify.rs | 42 -------------------- crates/libs/metadata/src/reader.rs | 19 +++++++-- crates/libs/metadata/src/tables.rs | 4 +- crates/libs/metadata/src/type.rs | 42 +++++++------------- 16 files changed, 117 insertions(+), 164 deletions(-) delete mode 100644 crates/libs/bindgen/src/winmd/verify.rs diff --git a/crates/libs/bindgen/src/lib.rs b/crates/libs/bindgen/src/lib.rs index ea371d34d0..439b85a545 100644 --- a/crates/libs/bindgen/src/lib.rs +++ b/crates/libs/bindgen/src/lib.rs @@ -111,8 +111,6 @@ where let input = read_input(&input)?; let reader = metadata::Reader::filter(input, &include, &exclude, &config); - winmd::verify(reader)?; - match extension(&output) { "rdl" => rdl::from_reader(reader, config, &output)?, "winmd" => winmd::from_reader(reader, config, &output)?, diff --git a/crates/libs/bindgen/src/metadata.rs b/crates/libs/bindgen/src/metadata.rs index fc476280ce..a06e2d46e6 100644 --- a/crates/libs/bindgen/src/metadata.rs +++ b/crates/libs/bindgen/src/metadata.rs @@ -157,7 +157,7 @@ impl Signature { match &self.return_type { Type::Void if self.is_retval() => SignatureKind::ReturnValue, Type::Void => SignatureKind::ReturnVoid, - Type::HRESULT => { + Type::Name(TypeName::HResult) => { if self.params.len() >= 2 { if let Some((guid, object)) = signature_param_is_query(&self.params) { if self.params[object].def.flags().contains(ParamAttributes::Optional) { @@ -357,7 +357,7 @@ fn param_or_enum(row: Param) -> Option { } fn signature_param_is_query(params: &[SignatureParam]) -> Option<(usize, usize)> { - if let Some(guid) = params.iter().rposition(|param| param.ty == Type::ConstPtr(Box::new(Type::GUID), 1) && !param.def.flags().contains(ParamAttributes::Out)) { + if let Some(guid) = params.iter().rposition(|param| param.ty == Type::ConstPtr(Box::new(Type::Name(TypeName::GUID)), 1) && !param.def.flags().contains(ParamAttributes::Out)) { if let Some(object) = params.iter().rposition(|param| param.ty == Type::MutPtr(Box::new(Type::Void), 2) && param.def.has_attribute("ComOutPtrAttribute")) { return Some((guid, object)); } @@ -377,7 +377,7 @@ fn method_def_last_error(row: MethodDef) -> bool { pub fn type_is_borrowed(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => !type_def_is_blittable(*row), - Type::BSTR | Type::VARIANT | Type::PROPVARIANT | Type::PCSTR | Type::PCWSTR | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => true, + Type::Name(TypeName::BSTR) | Type::Name(TypeName::VARIANT) | Type::Name(TypeName::PROPVARIANT) | Type::Const(TypeName::PSTR) | Type::Const(TypeName::PWSTR) | Type::Object | Type::Name(TypeName::IUnknown) | Type::GenericParam(_) => true, _ => false, } } @@ -506,7 +506,7 @@ pub fn field_is_copyable(row: Field, enclosing: TypeDef) -> bool { pub fn type_is_blittable(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => type_def_is_blittable(*row), - Type::String | Type::BSTR | Type::VARIANT | Type::PROPVARIANT | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => false, + Type::String | Type::Name(TypeName::BSTR) | Type::Name(TypeName::VARIANT) | Type::Name(TypeName::PROPVARIANT) | Type::Object | Type::Name(TypeName::IUnknown) | Type::GenericParam(_) => false, Type::Win32Array(kind, _) => type_is_blittable(kind), Type::WinrtArray(kind) => type_is_blittable(kind), _ => true, @@ -516,7 +516,7 @@ pub fn type_is_blittable(ty: &Type) -> bool { fn type_is_copyable(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => type_def_is_copyable(*row), - Type::String | Type::BSTR | Type::VARIANT | Type::PROPVARIANT | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => false, + Type::String | Type::Name(TypeName::BSTR) | Type::Name(TypeName::VARIANT) | Type::Name(TypeName::PROPVARIANT) | Type::Object | Type::Name(TypeName::IUnknown) | Type::GenericParam(_) => false, Type::Win32Array(kind, _) => type_is_copyable(kind), Type::WinrtArray(kind) => type_is_copyable(kind), _ => true, @@ -557,7 +557,7 @@ pub fn type_is_struct(ty: &Type) -> bool { // nested structs. Fortunately, this is rare enough that this check is sufficient. match ty { Type::TypeDef(row, _) => row.kind() == TypeKind::Struct && !type_def_is_handle(*row), - Type::GUID => true, + Type::Name(TypeName::GUID) => true, _ => false, } } @@ -574,7 +574,7 @@ fn type_def_is_primitive(row: TypeDef) -> bool { pub fn type_is_primitive(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => type_def_is_primitive(*row), - Type::Bool | Type::Char | Type::I8 | Type::U8 | Type::I16 | Type::U16 | Type::I32 | Type::U32 | Type::I64 | Type::U64 | Type::F32 | Type::F64 | Type::ISize | Type::USize | Type::HRESULT | Type::ConstPtr(_, _) | Type::MutPtr(_, _) => true, + Type::Bool | Type::Char | Type::I8 | Type::U8 | Type::I16 | Type::U16 | Type::I32 | Type::U32 | Type::I64 | Type::U64 | Type::F32 | Type::F64 | Type::ISize | Type::USize | Type::Name(TypeName::HResult) | Type::ConstPtr(_, _) | Type::MutPtr(_, _) => true, _ => false, } } @@ -675,9 +675,9 @@ fn type_signature(ty: &Type) -> String { Type::ISize => "is".to_string(), Type::USize => "us".to_string(), Type::String => "string".to_string(), - Type::IInspectable => "cinterface(IInspectable)".to_string(), - Type::GUID => "g16".to_string(), - Type::HRESULT => "struct(Windows.Foundation.HResult;i4)".to_string(), + Type::Object => "cinterface(IInspectable)".to_string(), + Type::Name(TypeName::GUID) => "g16".to_string(), + Type::Name(TypeName::HResult) => "struct(Windows.Foundation.HResult;i4)".to_string(), Type::TypeDef(row, generics) => type_def_signature(*row, generics), rest => unimplemented!("{rest:?}"), } @@ -775,7 +775,7 @@ fn type_def_is_nullable(row: TypeDef) -> bool { pub fn type_is_nullable(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => type_def_is_nullable(*row), - Type::IInspectable | Type::IUnknown => true, + Type::Object | Type::Name(TypeName::IUnknown) => true, _ => false, } } @@ -783,9 +783,9 @@ pub fn type_is_nullable(ty: &Type) -> bool { pub fn type_def_vtables(row: TypeDef) -> Vec { let mut result = Vec::new(); if row.flags().contains(TypeAttributes::WindowsRuntime) { - result.push(Type::IUnknown); + result.push(Type::Name(TypeName::IUnknown)); if row.kind() != TypeKind::Delegate { - result.push(Type::IInspectable); + result.push(Type::Object); } } else { let mut next = row; @@ -795,13 +795,13 @@ pub fn type_def_vtables(row: TypeDef) -> Vec { next = row; result.insert(0, base); } - Type::IInspectable => { - result.insert(0, Type::IUnknown); - result.insert(1, Type::IInspectable); + Type::Object => { + result.insert(0, Type::Name(TypeName::IUnknown)); + result.insert(1, Type::Object); break; } - Type::IUnknown => { - result.insert(0, Type::IUnknown); + Type::Name(TypeName::IUnknown) => { + result.insert(0, Type::Name(TypeName::IUnknown)); break; } rest => unimplemented!("{rest:?}"), diff --git a/crates/libs/bindgen/src/rdl/from_reader.rs b/crates/libs/bindgen/src/rdl/from_reader.rs index 58de71f05a..0cbd831532 100644 --- a/crates/libs/bindgen/src/rdl/from_reader.rs +++ b/crates/libs/bindgen/src/rdl/from_reader.rs @@ -339,11 +339,15 @@ impl Writer { // TODO: dialect-specific keywords for "well-known types" that don't map to metadata in all cases. metadata::Type::String => quote! { HSTRING }, - metadata::Type::HRESULT => quote! { HRESULT }, - metadata::Type::GUID => quote! { GUID }, - metadata::Type::IInspectable => quote! { IInspectable }, - metadata::Type::IUnknown => quote! { IUnknown }, - + metadata::Type::Name(metadata::TypeName::HResult) => quote! { HRESULT }, + metadata::Type::Name(metadata::TypeName::GUID) => quote! { GUID }, + metadata::Type::Object => quote! { IInspectable }, + metadata::Type::Name(metadata::TypeName::IUnknown) => quote! { IUnknown }, + metadata::Type::Name(metadata::TypeName::BSTR) => quote! { BSTR }, + metadata::Type::Name(metadata::TypeName::PSTR) => quote! { PSTR }, + metadata::Type::Name(metadata::TypeName::PWSTR) => quote! { PWSTR }, + metadata::Type::Const(metadata::TypeName::PSTR) => quote! { PCSTR }, + metadata::Type::Const(metadata::TypeName::PWSTR) => quote! { PCWSTR }, metadata::Type::TypeDef(def, generics) => { let namespace = self.namespace(def.namespace()); let name = to_ident(def.name()); @@ -355,7 +359,7 @@ impl Writer { } } - metadata::Type::TypeRef(type_name) => { + metadata::Type::Name(type_name) => { let namespace = self.namespace(type_name.namespace()); let name = to_ident(type_name.name()); quote! { #namespace #name } @@ -368,12 +372,6 @@ impl Writer { metadata::Type::MutPtr(ty, _pointers) => self.ty(ty), metadata::Type::ConstPtr(ty, _pointers) => self.ty(ty), metadata::Type::Win32Array(ty, _len) => self.ty(ty), - // TODO: these types should just be regular metadata type defs - metadata::Type::PSTR => quote! { PSTR }, - metadata::Type::PWSTR => quote! { PWSTR }, - metadata::Type::PCSTR => quote! { PCSTR }, - metadata::Type::PCWSTR => quote! { PCWSTR }, - metadata::Type::BSTR => quote! { BSTR }, metadata::Type::PrimitiveOrEnum(_, ty) => self.ty(ty), rest => unimplemented!("{rest:?}"), } diff --git a/crates/libs/bindgen/src/rust/constants.rs b/crates/libs/bindgen/src/rust/constants.rs index 7aee3b8193..9f54e99690 100644 --- a/crates/libs/bindgen/src/rust/constants.rs +++ b/crates/libs/bindgen/src/rust/constants.rs @@ -62,7 +62,7 @@ pub fn writer(writer: &Writer, def: metadata::Field) -> TokenStream { } } else if let Some(guid) = field_guid(def) { let value = writer.guid(&guid); - let guid = writer.type_name(&metadata::Type::GUID); + let guid = writer.type_name(&metadata::Type::Name(metadata::TypeName::GUID)); quote! { pub const #name: #guid = #value; } @@ -80,7 +80,7 @@ pub fn writer(writer: &Writer, def: metadata::Field) -> TokenStream { fn is_signed_error(ty: &metadata::Type) -> bool { match ty { - metadata::Type::HRESULT => true, + metadata::Type::Name(metadata::TypeName::HResult) => true, metadata::Type::TypeDef(def, _) => def.type_name() == metadata::TypeName::NTSTATUS, _ => false, } @@ -109,7 +109,7 @@ fn field_initializer<'a>(writer: &Writer, field: metadata::Field, input: &'a str let name = to_ident(field.name()); match field.ty(None) { - metadata::Type::GUID => { + metadata::Type::Name(metadata::TypeName::GUID) => { let (literals, rest) = read_literal_array(input, 11); let value = writer.guid(&metadata::Guid::from_string_args(&literals)); (quote! { #name: #value, }, rest) @@ -137,7 +137,7 @@ fn constant(def: metadata::Field) -> Option { def.find_attribute("ConstantAttribute").map(|attribute| { let args = attribute.args(); match &args[0].1 { - metadata::Value::String(value) => value.clone(), + metadata::Value::String(value) => value.to_string(), rest => unimplemented!("{rest:?}"), } }) @@ -200,7 +200,7 @@ fn field_is_ansi(row: metadata::Field) -> bool { fn type_has_replacement(ty: &metadata::Type) -> bool { match ty { - metadata::Type::HRESULT | metadata::Type::PCSTR | metadata::Type::PCWSTR => true, + metadata::Type::Name(metadata::TypeName::HResult) | metadata::Type::Const(metadata::TypeName::PSTR) | metadata::Type::Const(metadata::TypeName::PWSTR) => true, metadata::Type::TypeDef(row, _) => metadata::type_def_is_handle(*row) || row.kind() == metadata::TypeKind::Enum, _ => false, } @@ -209,7 +209,7 @@ fn type_has_replacement(ty: &metadata::Type) -> bool { fn type_underlying_type(ty: &metadata::Type) -> metadata::Type { match ty { metadata::Type::TypeDef(row, _) => row.underlying_type(), - metadata::Type::HRESULT => metadata::Type::I32, + metadata::Type::Name(metadata::TypeName::HResult) => metadata::Type::I32, _ => ty.clone(), } } diff --git a/crates/libs/bindgen/src/rust/implements.rs b/crates/libs/bindgen/src/rust/implements.rs index 9968be3a42..98000bfeec 100644 --- a/crates/libs/bindgen/src/rust/implements.rs +++ b/crates/libs/bindgen/src/rust/implements.rs @@ -24,7 +24,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let mut requires = quote! {}; let type_ident = quote! { #type_ident<#generic_names> }; let vtables = metadata::type_def_vtables(def); - let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::IUnknown)); + let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::Name(metadata::TypeName::IUnknown))); fn gen_required_trait(writer: &Writer, def: metadata::TypeDef, generics: &[metadata::Type]) -> TokenStream { let name = writer.type_def_name_imp(def, generics, "_Impl"); @@ -104,8 +104,8 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let mut methods = quote! {}; match vtables.last() { - Some(metadata::Type::IUnknown) => methods.combine("e! { base__: windows_core::IUnknown_Vtbl::new::(), }), - Some(metadata::Type::IInspectable) => methods.combine("e! { base__: windows_core::IInspectable_Vtbl::new::(), }), + Some(metadata::Type::Name(metadata::TypeName::IUnknown)) => methods.combine("e! { base__: windows_core::IUnknown_Vtbl::new::(), }), + Some(metadata::Type::Object) => methods.combine("e! { base__: windows_core::IInspectable_Vtbl::new::(), }), Some(metadata::Type::TypeDef(def, generics)) => { let name = writer.type_def_name_imp(*def, generics, "_Vtbl"); if has_unknown_base { diff --git a/crates/libs/bindgen/src/rust/interfaces.rs b/crates/libs/bindgen/src/rust/interfaces.rs index 0cdb6c74ca..8477d0661e 100644 --- a/crates/libs/bindgen/src/rust/interfaces.rs +++ b/crates/libs/bindgen/src/rust/interfaces.rs @@ -14,7 +14,7 @@ fn gen_sys_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)); + let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::Name(metadata::TypeName::IUnknown))); let mut tokens = quote! {}; @@ -42,7 +42,7 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream { let features = writer.cfg_features(&cfg); let interfaces = metadata::type_interfaces(&metadata::Type::TypeDef(def, generics.to_vec())); let vtables = metadata::type_def_vtables(def); - let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::IUnknown)); + let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::Name(metadata::TypeName::IUnknown))); let mut tokens = quote! {}; diff --git a/crates/libs/bindgen/src/rust/mod.rs b/crates/libs/bindgen/src/rust/mod.rs index 53cf1a0dc9..b453ec194d 100644 --- a/crates/libs/bindgen/src/rust/mod.rs +++ b/crates/libs/bindgen/src/rust/mod.rs @@ -225,7 +225,7 @@ fn namespace(writer: &Writer, tree: &Tree) -> String { fn namespace_impl(writer: &Writer, tree: &Tree) -> String { let writer = &mut writer.clone(); writer.namespace = tree.namespace; - let mut types = std::collections::BTreeMap::<&str, TokenStream>::new(); + let mut types = std::collections::BTreeMap::new(); for item in writer.reader.namespace_items(tree.namespace) { if let metadata::Item::Type(def) = item { diff --git a/crates/libs/bindgen/src/rust/standalone.rs b/crates/libs/bindgen/src/rust/standalone.rs index a27e195809..c9d52c3e4f 100644 --- a/crates/libs/bindgen/src/rust/standalone.rs +++ b/crates/libs/bindgen/src/rust/standalone.rs @@ -20,8 +20,8 @@ pub fn standalone_imp(writer: &Writer) -> String { for ty in types { match ty { - metadata::Type::HRESULT if writer.sys => sorted.insert("HRESULT", quote! { pub type HRESULT = i32; }), - metadata::Type::IUnknown if writer.sys => sorted.insert( + metadata::Type::Name(metadata::TypeName::HResult) if writer.sys => sorted.insert("HRESULT", quote! { pub type HRESULT = i32; }), + metadata::Type::Name(metadata::TypeName::IUnknown) if writer.sys => sorted.insert( "IUnknown", if !writer.vtbl { quote! {} @@ -37,7 +37,7 @@ pub fn standalone_imp(writer: &Writer) -> String { } }, ), - metadata::Type::IInspectable if writer.sys => sorted.insert( + metadata::Type::Object if writer.sys => sorted.insert( "IInspectable", if !writer.vtbl { quote! {} @@ -54,12 +54,12 @@ pub fn standalone_imp(writer: &Writer) -> String { } }, ), - metadata::Type::PSTR if writer.sys => sorted.insert("PSTR", quote! { pub type PSTR = *mut u8; }), - metadata::Type::PWSTR if writer.sys => sorted.insert("PWSTR", quote! { pub type PWSTR = *mut u16; }), - metadata::Type::PCSTR if writer.sys => sorted.insert("PCSTR", quote! { pub type PCSTR = *const u8; }), - metadata::Type::PCWSTR if writer.sys => sorted.insert("PCWSTR", quote! { pub type PCWSTR = *const u16; }), - metadata::Type::BSTR if writer.sys => sorted.insert("BSTR", quote! { pub type BSTR = *const u16; }), - metadata::Type::GUID if writer.sys => { + metadata::Type::Name(metadata::TypeName::PSTR) if writer.sys => sorted.insert("PSTR", quote! { pub type PSTR = *mut u8; }), + metadata::Type::Name(metadata::TypeName::PWSTR) if writer.sys => sorted.insert("PWSTR", quote! { pub type PWSTR = *mut u16; }), + metadata::Type::Const(metadata::TypeName::PSTR) if writer.sys => sorted.insert("PCSTR", quote! { pub type PCSTR = *const u8; }), + metadata::Type::Const(metadata::TypeName::PWSTR) if writer.sys => sorted.insert("PCWSTR", quote! { pub type PCWSTR = *const u16; }), + metadata::Type::Name(metadata::TypeName::BSTR) if writer.sys => sorted.insert("BSTR", quote! { pub type BSTR = *const u16; }), + metadata::Type::Name(metadata::TypeName::GUID) if writer.sys => { sorted.insert( "GUID", quote! { @@ -128,11 +128,11 @@ fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std:: if writer.vtbl { match ty { - metadata::Type::IUnknown => { - set.insert(metadata::Type::GUID); - set.insert(metadata::Type::HRESULT); + metadata::Type::Name(metadata::TypeName::IUnknown) => { + set.insert(metadata::Type::Name(metadata::TypeName::GUID)); + set.insert(metadata::Type::Name(metadata::TypeName::HResult)); } - metadata::Type::IInspectable => type_collect_standalone(writer, &metadata::Type::IUnknown, set), + metadata::Type::Object => type_collect_standalone(writer, &metadata::Type::Name(metadata::TypeName::IUnknown), set), _ => {} } } @@ -188,12 +188,12 @@ fn type_collect_standalone(writer: &Writer, ty: &metadata::Type, set: &mut std:: match def.kind() { metadata::TypeKind::Struct => { if def.fields().next().is_none() && metadata::type_def_guid(def).is_some() { - set.insert(metadata::Type::GUID); + set.insert(metadata::Type::Name(metadata::TypeName::GUID)); } } metadata::TypeKind::Interface => { if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) { - type_collect_standalone(writer, &metadata::Type::IInspectable, set); + type_collect_standalone(writer, &metadata::Type::Object, set); } } _ => {} diff --git a/crates/libs/bindgen/src/rust/structs.rs b/crates/libs/bindgen/src/rust/structs.rs index 0a1f67fb26..fb923bb23d 100644 --- a/crates/libs/bindgen/src/rust/structs.rs +++ b/crates/libs/bindgen/src/rust/structs.rs @@ -13,7 +13,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream { if let Some(guid) = clsid(def) { let ident = to_ident(def.name()); let value = writer.guid(&guid); - let guid = writer.type_name(&metadata::Type::GUID); + let guid = writer.type_name(&metadata::Type::Name(metadata::TypeName::GUID)); return quote! { pub const #ident: #guid = #value; }; diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index 16e9bb81fa..18426da236 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -141,19 +141,19 @@ impl Writer { quote! { #crate_name HSTRING } } } - metadata::Type::BSTR => { + metadata::Type::Name(metadata::TypeName::BSTR) => { let crate_name = self.crate_name(); quote! { #crate_name BSTR } } - metadata::Type::VARIANT => { + metadata::Type::Name(metadata::TypeName::VARIANT) => { let crate_name = self.crate_name(); quote! { #crate_name VARIANT } } - metadata::Type::PROPVARIANT => { + metadata::Type::Name(metadata::TypeName::PROPVARIANT) => { let crate_name = self.crate_name(); quote! { #crate_name PROPVARIANT } } - metadata::Type::IInspectable => { + metadata::Type::Object => { if self.sys { quote! { *mut core::ffi::c_void } } else { @@ -161,11 +161,11 @@ impl Writer { quote! { #crate_name IInspectable } } } - metadata::Type::GUID => { + metadata::Type::Name(metadata::TypeName::GUID) => { let crate_name = self.crate_name(); quote! { #crate_name GUID } } - metadata::Type::IUnknown => { + metadata::Type::Name(metadata::TypeName::IUnknown) => { if self.sys { quote! { *mut core::ffi::c_void } } else { @@ -173,23 +173,23 @@ impl Writer { quote! { #crate_name IUnknown } } } - metadata::Type::HRESULT => { + metadata::Type::Name(metadata::TypeName::HResult) => { let crate_name = self.crate_name(); quote! { #crate_name HRESULT } } - metadata::Type::PSTR => { + metadata::Type::Name(metadata::TypeName::PSTR) => { let crate_name = self.crate_name(); quote! { #crate_name PSTR } } - metadata::Type::PWSTR => { + metadata::Type::Name(metadata::TypeName::PWSTR) => { let crate_name = self.crate_name(); quote! { #crate_name PWSTR } } - metadata::Type::PCSTR => { + metadata::Type::Const(metadata::TypeName::PSTR) => { let crate_name = self.crate_name(); quote! { #crate_name PCSTR } } - metadata::Type::PCWSTR => { + metadata::Type::Const(metadata::TypeName::PWSTR) => { let crate_name = self.crate_name(); quote! { #crate_name PCWSTR } } @@ -242,19 +242,19 @@ impl Writer { } match ty { - metadata::Type::IUnknown | metadata::Type::IInspectable => { + metadata::Type::Name(metadata::TypeName::IUnknown) | metadata::Type::Object => { quote! { *mut core::ffi::c_void } } metadata::Type::String => { quote! { std::mem::MaybeUninit } } - metadata::Type::BSTR => { + metadata::Type::Name(metadata::TypeName::BSTR) => { quote! { std::mem::MaybeUninit } } - metadata::Type::VARIANT => { + metadata::Type::Name(metadata::TypeName::VARIANT) => { quote! { std::mem::MaybeUninit } } - metadata::Type::PROPVARIANT => { + metadata::Type::Name(metadata::TypeName::PROPVARIANT) => { quote! { std::mem::MaybeUninit } } metadata::Type::Win32Array(kind, len) => { @@ -561,7 +561,7 @@ impl Writer { } pub fn guid(&self, value: &metadata::Guid) -> TokenStream { - let guid = self.type_name(&metadata::Type::GUID); + let guid = self.type_name(&metadata::Type::Name(metadata::TypeName::GUID)); format!("{}::from_u128(0x{:08x?}_{:04x?}_{:04x?}_{:02x?}{:02x?}_{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?})", guid.into_string(), value.0, value.1, value.2, value.3, value.4, value.5, value.6, value.7, value.8, value.9, value.10).into() } @@ -781,8 +781,8 @@ impl Writer { let crate_name = self.crate_name(); match metadata::type_def_vtables(def).last() { - Some(metadata::Type::IUnknown) => methods.combine("e! { pub base__: #crate_name IUnknown_Vtbl, }), - Some(metadata::Type::IInspectable) => methods.combine("e! { pub base__: #crate_name IInspectable_Vtbl, }), + Some(metadata::Type::Name(metadata::TypeName::IUnknown)) => methods.combine("e! { pub base__: #crate_name IUnknown_Vtbl, }), + Some(metadata::Type::Object) => methods.combine("e! { pub base__: #crate_name IInspectable_Vtbl, }), Some(metadata::Type::TypeDef(def, _)) => { let vtbl = self.type_def_vtbl_name(*def, &[]); methods.combine("e! { pub base__: #vtbl, }); diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index 3717e57e97..c596ce85d2 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -185,16 +185,16 @@ fn winmd_type(ty: &metadata::Type) -> Type { metadata::Type::ISize => Type::ISize, metadata::Type::USize => Type::USize, metadata::Type::String => Type::String, - metadata::Type::GUID => Type::GUID, - metadata::Type::IUnknown => Type::IUnknown, - metadata::Type::IInspectable => Type::IInspectable, - metadata::Type::HRESULT => Type::HRESULT, - metadata::Type::PSTR => Type::PSTR, - metadata::Type::PWSTR => Type::PWSTR, - metadata::Type::PCSTR => Type::PCSTR, - metadata::Type::PCWSTR => Type::PCWSTR, - metadata::Type::BSTR => Type::BSTR, - metadata::Type::Type => Type::Type, + metadata::Type::Name(metadata::TypeName::GUID) => Type::GUID, + metadata::Type::Name(metadata::TypeName::IUnknown) => Type::IUnknown, + metadata::Type::Object => Type::IInspectable, + metadata::Type::Name(metadata::TypeName::HResult) => Type::HRESULT, + metadata::Type::Name(metadata::TypeName::PSTR) => Type::PSTR, + metadata::Type::Name(metadata::TypeName::PWSTR) => Type::PWSTR, + metadata::Type::Const(metadata::TypeName::PSTR) => Type::PCSTR, + metadata::Type::Const(metadata::TypeName::PWSTR) => Type::PCWSTR, + metadata::Type::Name(metadata::TypeName::BSTR) => Type::BSTR, + metadata::Type::Name(metadata::TypeName::Type) => Type::Type, metadata::Type::TypeDef(def, generics) => Type::TypeRef(TypeName { namespace: def.namespace().to_string(), name: def.name().to_string(), generics: generics.iter().map(winmd_type).collect() }), metadata::Type::GenericParam(generic) => Type::GenericParam(generic.number()), metadata::Type::ConstRef(ty) => Type::ConstRef(Box::new(winmd_type(ty))), diff --git a/crates/libs/bindgen/src/winmd/mod.rs b/crates/libs/bindgen/src/winmd/mod.rs index f01afa218a..3ee7c6d079 100644 --- a/crates/libs/bindgen/src/winmd/mod.rs +++ b/crates/libs/bindgen/src/winmd/mod.rs @@ -1,7 +1,5 @@ mod from_reader; -mod verify; pub mod writer; use super::*; pub use from_reader::from_reader; -pub use verify::verify; pub use writer::*; diff --git a/crates/libs/bindgen/src/winmd/verify.rs b/crates/libs/bindgen/src/winmd/verify.rs deleted file mode 100644 index f322b6ce62..0000000000 --- a/crates/libs/bindgen/src/winmd/verify.rs +++ /dev/null @@ -1,42 +0,0 @@ -use super::*; - -pub fn verify(reader: &metadata::Reader) -> Result<()> { - let unused: Vec<&str> = reader.unused().collect(); - - if !unused.is_empty() { - let mut message = "unused filters".to_string(); - - for unused in unused { - message.push_str(&format!("\n {unused}")); - } - - return Err(Error::new(&message)); - } - - for item in reader.items() { - // TODO: cover all variants - let metadata::Item::Type(def) = item else { - continue; - }; - - let generics = &metadata::type_def_generics(def); - - def.fields().try_for_each(|field| not_type_ref(&field.ty(Some(def))))?; - - def.methods().try_for_each(|method| { - let sig = method.signature(generics); - not_type_ref(&sig.return_type)?; - - sig.params.iter().try_for_each(not_type_ref) - })?; - } - - Ok(()) -} - -fn not_type_ref(ty: &metadata::Type) -> Result<()> { - if let metadata::Type::TypeRef(ty) = ty { - return Err(Error::new(&format!("missing type definition `{}`", ty))); - } - Ok(()) -} diff --git a/crates/libs/metadata/src/reader.rs b/crates/libs/metadata/src/reader.rs index dde96866ec..73b90d0a3c 100644 --- a/crates/libs/metadata/src/reader.rs +++ b/crates/libs/metadata/src/reader.rs @@ -183,7 +183,7 @@ impl Reader { if let Some(def) = self.get_type_def(full_name.namespace(), full_name.name()).next() { Type::TypeDef(def, Vec::new()) } else { - Type::TypeRef(full_name) + Type::Name(full_name) } } @@ -263,5 +263,18 @@ impl Reader { const REMAP_TYPES: [(TypeName, TypeName); 3] = [(TypeName::D2D_MATRIX_3X2_F, TypeName::Matrix3x2), (TypeName::D3DMATRIX, TypeName::Matrix4x4), (TypeName::HRESULT, TypeName::HResult)]; // TODO: get rid of at least the second tuple if not the whole thing. -const CORE_TYPES: [(TypeName, Type); 12] = [(TypeName::GUID, Type::GUID), (TypeName::IUnknown, Type::IUnknown), (TypeName::HResult, Type::HRESULT), (TypeName::HSTRING, Type::String), (TypeName::BSTR, Type::BSTR), (TypeName::IInspectable, Type::IInspectable), (TypeName::PSTR, Type::PSTR), (TypeName::PWSTR, Type::PWSTR), (TypeName::Type, Type::Type), (TypeName::CHAR, Type::I8), (TypeName::VARIANT, Type::VARIANT), (TypeName::PROPVARIANT, Type::PROPVARIANT)]; -const SYS_CORE_TYPES: [(TypeName, Type); 10] = [(TypeName::GUID, Type::GUID), (TypeName::IUnknown, Type::IUnknown), (TypeName::HResult, Type::HRESULT), (TypeName::HSTRING, Type::String), (TypeName::BSTR, Type::BSTR), (TypeName::IInspectable, Type::IInspectable), (TypeName::PSTR, Type::PSTR), (TypeName::PWSTR, Type::PWSTR), (TypeName::Type, Type::Type), (TypeName::CHAR, Type::I8)]; +const CORE_TYPES: [(TypeName, Type); 12] = [ + (TypeName::GUID, Type::Name(TypeName::GUID)), + (TypeName::IUnknown, Type::Name(TypeName::IUnknown)), + (TypeName::HResult, Type::Name(TypeName::HResult)), + (TypeName::HSTRING, Type::String), + (TypeName::BSTR, Type::Name(TypeName::BSTR)), + (TypeName::IInspectable, Type::Object), + (TypeName::PSTR, Type::Name(TypeName::PSTR)), + (TypeName::PWSTR, Type::Name(TypeName::PWSTR)), + (TypeName::Type, Type::Name(TypeName::Type)), + (TypeName::CHAR, Type::I8), + (TypeName::VARIANT, Type::Name(TypeName::VARIANT)), + (TypeName::PROPVARIANT, Type::Name(TypeName::PROPVARIANT)), +]; +const SYS_CORE_TYPES: [(TypeName, Type); 10] = [(TypeName::GUID, Type::Name(TypeName::GUID)), (TypeName::IUnknown, Type::Name(TypeName::IUnknown)), (TypeName::HResult, Type::Name(TypeName::HResult)), (TypeName::HSTRING, Type::String), (TypeName::BSTR, Type::Name(TypeName::BSTR)), (TypeName::IInspectable, Type::Object), (TypeName::PSTR, Type::Name(TypeName::PSTR)), (TypeName::PWSTR, Type::Name(TypeName::PWSTR)), (TypeName::Type, Type::Name(TypeName::Type)), (TypeName::CHAR, Type::I8)]; diff --git a/crates/libs/metadata/src/tables.rs b/crates/libs/metadata/src/tables.rs index 1f8c83fe0d..296549ac92 100644 --- a/crates/libs/metadata/src/tables.rs +++ b/crates/libs/metadata/src/tables.rs @@ -1,5 +1,7 @@ use super::*; +// TODO: maybe manually define TypeDef here to include generics + macro_rules! tables { ($(($name:ident, $table:literal))+) => { $( @@ -85,7 +87,7 @@ impl Attribute { Type::I64 => Value::I64(values.read_i64()), Type::U64 => Value::U64(values.read_u64()), Type::String => Value::String(values.read_str().to_string()), - Type::Type => Value::TypeName(TypeName::parse(values.read_str())), + Type::Name(TypeName::Type) => Value::TypeName(TypeName::parse(values.read_str())), Type::TypeDef(def, _) => Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type()))), rest => unimplemented!("{rest:?}"), }; diff --git a/crates/libs/metadata/src/type.rs b/crates/libs/metadata/src/type.rs index 012fb6f31a..dde508160d 100644 --- a/crates/libs/metadata/src/type.rs +++ b/crates/libs/metadata/src/type.rs @@ -1,5 +1,6 @@ use super::*; +// Note: Type::Name(TypeName) is preferred since we can use it in pattern matching whereas Type::TypeDef can't be used in that way. #[derive(Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)] pub enum Type { // Primitives in ECMA-335 @@ -18,19 +19,15 @@ pub enum Type { F64, ISize, USize, + String, // TODO: Win32 should use System.String when referring to an HSTRING + Object, // TODO: Win32 should use System.Object when referring to an IInspectable - // System types - GUID, // Both Win32 and WinRT agree that this is represented by System.Guid - String, // TODO: Win32 should use System.String when referring to an HSTRING - IInspectable, // TODO: Win32 should use System.Object when referring to an IInspectable - Type, // System.Type is needed since WinRT attribute use this as a parameter type. + Name(TypeName), + Const(TypeName), - // Regular ECMA-335 types that map to metadata - TypeRef(TypeName), GenericParam(GenericParam), - TypeDef(TypeDef, Vec), + TypeDef(TypeDef, Vec), // TODO: store generics inside TypeDef to simplify this - // Qualified types MutPtr(Box, usize), ConstPtr(Box, usize), Win32Array(Box, usize), @@ -40,17 +37,6 @@ pub enum Type { // TODO: temporary hack to accommodate Win32 metadata PrimitiveOrEnum(Box, Box), - - // TODO: these should not be "special" and just point to regular metadata types in Win32.Foundation - HRESULT, // TODO: Win32 should use Windows.Foundation.HResult when referring to HRESULT - IUnknown, // TODO: should be defined in Windows.Win32.Foundation.IUnknown - PSTR, - PWSTR, - PCSTR, - PCWSTR, - BSTR, - VARIANT, - PROPVARIANT, } impl Type { @@ -74,7 +60,7 @@ impl Type { ELEMENT_TYPE_I => Some(Self::ISize), ELEMENT_TYPE_U => Some(Self::USize), ELEMENT_TYPE_STRING => Some(Self::String), - ELEMENT_TYPE_OBJECT => Some(Self::IInspectable), + ELEMENT_TYPE_OBJECT => Some(Self::Object), _ => None, } } @@ -84,8 +70,8 @@ impl Type { match self { Self::MutPtr(kind, pointers) => Self::MutPtr(Box::new(kind.to_const_type()), pointers), Self::ConstPtr(kind, pointers) => Self::ConstPtr(Box::new(kind.to_const_type()), pointers), - Self::PSTR => Self::PCSTR, - Self::PWSTR => Self::PCWSTR, + Self::Name(TypeName::PSTR) => Self::Const(TypeName::PSTR), + Self::Name(TypeName::PWSTR) => Self::Const(TypeName::PWSTR), _ => self, } } @@ -123,8 +109,8 @@ impl Type { } Self::ConstPtr(kind, pointers) => Self::ConstPtr(kind.clone(), pointers - 1), Self::MutPtr(kind, pointers) => Self::MutPtr(kind.clone(), pointers - 1), - Self::PSTR | Self::PCSTR => Self::U8, - Self::PWSTR | Self::PCWSTR => Self::U16, + Self::Name(TypeName::PSTR) | Self::Const(TypeName::PSTR) => Self::U8, + Self::Name(TypeName::PWSTR) | Self::Const(TypeName::PWSTR) => Self::U16, _ => panic!("`deref` can only be called on pointer types"), } } @@ -167,7 +153,7 @@ impl Type { pub fn is_byte_size(&self) -> bool { match self { Type::ConstPtr(kind, _) | Type::MutPtr(kind, _) => kind.is_byte_size(), - Type::I8 | Type::U8 | Type::PSTR | Type::PCSTR => true, + Type::I8 | Type::U8 | Self::Name(TypeName::PSTR) | Self::Const(TypeName::PSTR) => true, _ => false, } } @@ -177,7 +163,7 @@ impl Type { Type::I8 | Type::U8 => 1, Type::I16 | Type::U16 => 2, Type::I64 | Type::U64 | Type::F64 => 8, - Type::GUID => 16, + Type::Name(TypeName::GUID) => 16, Type::TypeDef(def, _) => def.size(), Type::Win32Array(ty, len) => ty.size() * len, Type::PrimitiveOrEnum(ty, _) => ty.size(), @@ -190,7 +176,7 @@ impl Type { Type::I8 | Type::U8 => 1, Type::I16 | Type::U16 => 2, Type::I64 | Type::U64 | Type::F64 => 8, - Type::GUID => 4, + Type::Name(TypeName::GUID) => 4, Type::TypeDef(def, _) => def.align(), Type::Win32Array(ty, len) => ty.align() * len, _ => 4,