diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index b39e5b9caa..e305b44213 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Clone)] pub struct Writer<'a> { - pub reader: &'a Reader<'a>, + pub reader: &'a Reader, pub filter: &'a metadata::Filter<'a>, pub output: &'a str, pub namespace: &'a str, @@ -36,7 +36,7 @@ impl<'a> Writer<'a> { self.type_def_name_imp(def, generics, "_Vtbl") } pub fn type_def_name_imp(&self, def: TypeDef, generics: &[Type], suffix: &str) -> TokenStream { - let type_name = self.reader.type_def_type_name(def); + let type_name = def.type_name(); if type_name.namespace.is_empty() { to_ident(&self.scoped_name(def)) @@ -73,7 +73,7 @@ impl<'a> Writer<'a> { if ty.is_generic() { quote! { <#kind as ::windows_core::Type<#kind>>::Default } - } else if type_is_nullable(self.reader, ty) && !self.sys { + } else if type_is_nullable(ty) && !self.sys { quote! { ::core::option::Option<#kind> } } else { kind @@ -143,7 +143,7 @@ impl<'a> Writer<'a> { let len = Literal::usize_unsuffixed(*len); quote! { [#name; #len] } } - Type::GenericParam(generic) => self.reader.generic_param_name(*generic).into(), + Type::GenericParam(generic) => generic.name().into(), Type::TypeDef(def, generics) => self.type_def_name(*def, generics), Type::MutPtr(ty, pointers) => { let pointers = mut_ptrs(*pointers); @@ -192,10 +192,10 @@ impl<'a> Writer<'a> { quote! { [#name; #len] } } Type::GenericParam(generic) => { - let name = to_ident(self.reader.generic_param_name(*generic)); + let name = to_ident(generic.name()); quote! { ::windows_core::AbiType<#name> } } - Type::TypeDef(def, _) => match self.reader.type_def_kind(*def) { + Type::TypeDef(def, _) => match def.kind() { TypeKind::Enum => self.type_def_name(*def, &[]), TypeKind::Struct => { let tokens = self.type_def_name(*def, &[]); @@ -206,7 +206,7 @@ impl<'a> Writer<'a> { } } TypeKind::Delegate => { - if self.reader.type_def_flags(*def).contains(TypeAttributes::WindowsRuntime) { + if def.flags().contains(TypeAttributes::WindowsRuntime) { quote! { *mut ::core::ffi::c_void } } else { self.type_def_name(*def, &[]) @@ -480,14 +480,14 @@ impl<'a> Writer<'a> { } } fn scoped_name(&self, def: TypeDef) -> String { - if let Some(enclosing_type) = self.reader.type_def_enclosing_type(def) { + if let Some(enclosing_type) = def.enclosing_type() { for (index, nested_type) in self.reader.nested_types(enclosing_type).enumerate() { - if self.reader.type_def_name(nested_type) == self.reader.type_def_name(def) { + if nested_type.name() == def.name() { return format!("{}_{index}", &self.scoped_name(enclosing_type)); } } } - self.reader.type_def_name(def).to_string() + def.name().to_string() } pub fn value(&self, value: &Value) -> TokenStream { match value { @@ -536,12 +536,12 @@ impl<'a> Writer<'a> { } } - pub fn guid(&self, value: &GUID) -> TokenStream { + pub fn guid(&self, value: &Guid) -> TokenStream { let guid = self.type_name(&Type::GUID); format!("{}::from_u128(0x{:08x?}_{:04x?}_{:04x?}_{:02x?}{:02x?}_{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?})", guid.into_string(), value.0, value.1, value.2, value.3, value.4, value.5, value.6, value.7, value.8, value.9, value.10).into() } pub fn agile(&self, def: TypeDef, ident: &TokenStream, constraints: &TokenStream, features: &TokenStream) -> TokenStream { - if type_def_is_agile(self.reader, def) { + if type_def_is_agile(def) { quote! { #features unsafe impl<#constraints> ::core::marker::Send for #ident {} @@ -553,13 +553,13 @@ impl<'a> Writer<'a> { } } pub fn async_get(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream { - let mut kind = type_def_async_kind(self.reader, def); + let mut kind = type_def_async_kind(def); let mut async_generics = generics.to_vec(); if kind == AsyncKind::None { - for interface in type_def_interfaces(self.reader, def, generics) { + for interface in type_def_interfaces(def, generics) { if let Type::TypeDef(interface_def, interface_generics) = &interface { - kind = type_def_async_kind(self.reader, *interface_def); + kind = type_def_async_kind(*interface_def); if kind != AsyncKind::None { async_generics = interface_generics.to_vec(); break; @@ -626,14 +626,14 @@ impl<'a> Writer<'a> { } } pub fn interface_winrt_trait(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream { - if self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) { - let type_signature = if self.reader.type_def_kind(def) == TypeKind::Class { + if def.flags().contains(TypeAttributes::WindowsRuntime) { + let type_signature = if def.kind() == TypeKind::Class { let type_signature = Literal::byte_string(type_def_signature(self.reader, def, generics).as_bytes()); quote! { ::windows_core::imp::ConstBuffer::from_slice(#type_signature) } } else { let signature = Literal::byte_string( // TODO: workaround for riddle winmd generation (no attribute support) - if let Some(guid) = type_def_guid(self.reader, def) { format!("{{{:#?}}}", guid) } else { "TODO".to_string() }.as_bytes(), + if let Some(guid) = type_def_guid(def) { format!("{{{:#?}}}", guid) } else { "TODO".to_string() }.as_bytes(), ); if generics.is_empty() { @@ -679,9 +679,9 @@ impl<'a> Writer<'a> { } } pub fn runtime_name_trait(&self, def: TypeDef, _generics: &[Type], name: &TokenStream, constraints: &TokenStream, features: &TokenStream) -> TokenStream { - if self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) { + if def.flags().contains(TypeAttributes::WindowsRuntime) { // TODO: this needs to use a ConstBuffer-like facility to accomodate generics - let runtime_name = format!("{}", self.reader.type_def_type_name(def)); + let runtime_name = format!("{}", def.type_name()); quote! { #features @@ -698,7 +698,7 @@ impl<'a> Writer<'a> { } pub fn interface_trait(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, features: &TokenStream, has_unknown_base: bool) -> TokenStream { - if let Some(default) = type_def_default_interface(self.reader, def) { + if let Some(default) = type_def_default_interface(def) { let default_name = self.type_name(&default); let vtbl = self.type_vtbl_name(&default); quote! { @@ -714,7 +714,7 @@ impl<'a> Writer<'a> { } else { let vtbl = self.type_def_vtbl_name(def, generics); let guid = if generics.is_empty() { - match type_def_guid(self.reader, def) { + match type_def_guid(def) { Some(guid) => self.guid(&guid), None => { quote! { @@ -751,10 +751,10 @@ impl<'a> Writer<'a> { let vtbl = self.type_def_vtbl_name(def, generics); let mut methods = quote! {}; let mut method_names = MethodNames::new(); - method_names.add_vtable_types(self, def); + method_names.add_vtable_types(def); let phantoms = self.generic_named_phantoms(generics); - match type_def_vtables(self.reader, def).last() { + match type_def_vtables(def).last() { Some(Type::IUnknown) => methods.combine("e! { pub base__: ::windows_core::IUnknown_Vtbl, }), Some(Type::IInspectable) => methods.combine("e! { pub base__: ::windows_core::IInspectable_Vtbl, }), Some(Type::TypeDef(def, _)) => { @@ -764,15 +764,15 @@ impl<'a> Writer<'a> { _ => {} } - for method in self.reader.type_def_methods(def) { - if self.reader.method_def_name(method) == ".ctor" { + for method in def.methods() { + if method.name() == ".ctor" { continue; } - let name = method_names.add(self, method); - let signature = method_def_signature(self.reader, self.reader.type_def_namespace(def), method, generics); + let name = method_names.add(method); + let signature = method_def_signature(self.reader, def.namespace(), method, generics); let mut cfg = signature_cfg(self.reader, method); let signature = self.vtbl_signature(def, generics, &signature); - cfg.add_feature(self.reader.type_def_namespace(def)); + cfg.add_feature(def.namespace()); let cfg_all = self.cfg_features(&cfg); let cfg_not = self.cfg_not_features(&cfg); @@ -799,7 +799,7 @@ impl<'a> Writer<'a> { } } pub fn vtbl_signature(&self, def: TypeDef, _generics: &[Type], signature: &Signature) -> TokenStream { - let is_winrt = self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime); + let is_winrt = def.flags().contains(TypeAttributes::WindowsRuntime); let crate_name = self.crate_name(); @@ -814,7 +814,7 @@ impl<'a> Writer<'a> { let tokens = self.type_abi_name(&signature.return_type); (quote! { result__: *mut #tokens }, quote! { -> #crate_name HRESULT }, quote! {}) } - _ if type_is_struct(self.reader, &signature.return_type) => { + _ if type_is_struct(&signature.return_type) => { let tokens = self.type_abi_name(&signature.return_type); (quote! {}, quote! {}, quote! { result__: *mut #tokens, }) } @@ -828,9 +828,9 @@ impl<'a> Writer<'a> { let name = self.param_name(p.def); if is_winrt { let abi = self.type_abi_name(&p.ty); - let abi_size_name: TokenStream = format!("{}_array_size", self.reader.param_name(p.def)).into(); + let abi_size_name: TokenStream = format!("{}_array_size", p.def.name()).into(); - if self.reader.param_flags(p.def).contains(ParamAttributes::In) { + if p.def.flags().contains(ParamAttributes::In) { if p.ty.is_winrt_array() { quote! { #abi_size_name: u32, #name: *const #abi, } } else if p.ty.is_const_ref() { @@ -864,11 +864,11 @@ impl<'a> Writer<'a> { pub fn param_name(&self, param: Param) -> TokenStream { // In Rust, function parameters cannot be named the same as structs. This avoids some collisions that occur in the win32 metadata. // See Icmp6SendEcho2 for an example. - to_ident(&self.reader.param_name(param).to_lowercase()) + to_ident(¶m.name().to_lowercase()) } pub fn return_sig(&self, signature: &Signature) -> TokenStream { match &signature.return_type { - Type::Void if self.reader.has_attribute(signature.def, "DoesNotReturnAttribute") => " -> !".into(), + Type::Void if signature.def.has_attribute("DoesNotReturnAttribute") => " -> !".into(), Type::Void => " -> ()".into(), _ => { let tokens = self.type_default_name(&signature.return_type); @@ -895,7 +895,7 @@ impl<'a> Writer<'a> { } _ => { let name = self.param_name(param.def); - let flags = self.reader.param_flags(param.def); + let flags = param.def.flags(); match param.kind { SignatureParamKind::ArrayFixed(_) | SignatureParamKind::ArrayRelativeLen(_) | SignatureParamKind::ArrayRelativeByteLen(_) => { let map = if flags.contains(ParamAttributes::Optional) { @@ -907,7 +907,7 @@ impl<'a> Writer<'a> { } SignatureParamKind::ArrayRelativePtr(relative) => { let name = self.param_name(params[relative].def); - let flags = self.reader.param_flags(params[relative].def); + let flags = params[relative].def.flags(); if flags.contains(ParamAttributes::Optional) { quote! { #name.as_deref().map_or(0, |slice|slice.len() as _), } } else { @@ -972,12 +972,12 @@ impl<'a> Writer<'a> { let ty = param.ty.deref(); let ty = self.type_default_name(&ty); let len = Literal::u32_unsuffixed(fixed as u32); - let ty = if self.reader.param_flags(param.def).contains(ParamAttributes::Out) { + let ty = if param.def.flags().contains(ParamAttributes::Out) { quote! { &mut [#ty; #len] } } else { quote! { &[#ty; #len] } }; - if self.reader.param_flags(param.def).contains(ParamAttributes::Optional) { + if param.def.flags().contains(ParamAttributes::Optional) { tokens.combine("e! { #name: ::core::option::Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); @@ -986,24 +986,24 @@ impl<'a> Writer<'a> { SignatureParamKind::ArrayRelativeLen(_) => { let ty = param.ty.deref(); let ty = self.type_default_name(&ty); - let ty = if self.reader.param_flags(param.def).contains(ParamAttributes::Out) { + let ty = if param.def.flags().contains(ParamAttributes::Out) { quote! { &mut [#ty] } } else { quote! { &[#ty] } }; - if self.reader.param_flags(param.def).contains(ParamAttributes::Optional) { + if param.def.flags().contains(ParamAttributes::Optional) { tokens.combine("e! { #name: ::core::option::Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); } } SignatureParamKind::ArrayRelativeByteLen(_) => { - let ty = if self.reader.param_flags(param.def).contains(ParamAttributes::Out) { + let ty = if param.def.flags().contains(ParamAttributes::Out) { quote! { &mut [u8] } } else { quote! { &[u8] } }; - if self.reader.param_flags(param.def).contains(ParamAttributes::Optional) { + if param.def.flags().contains(ParamAttributes::Optional) { tokens.combine("e! { #name: ::core::option::Option<#ty>, }); } else { tokens.combine("e! { #name: #ty, }); @@ -1034,8 +1034,8 @@ impl<'a> Writer<'a> { } pub fn impl_signature(&self, def: TypeDef, signature: &Signature) -> TokenStream { - if self.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) { - let is_delegate = self.reader.type_def_kind(def) == TypeKind::Delegate; + if def.flags().contains(TypeAttributes::WindowsRuntime) { + let is_delegate = def.kind() == TypeKind::Delegate; let params = signature.params.iter().map(|p| self.winrt_produce_type(p, !is_delegate)); let return_type = match &signature.return_type { @@ -1059,7 +1059,7 @@ impl<'a> Writer<'a> { quote! { (#this #(#params),*) -> ::windows_core::Result<#return_type> } } else { - let signature_kind = signature_kind(self.reader, signature); + let signature_kind = signature_kind(signature); let mut params = quote! {}; if signature_kind == SignatureKind::ResultValue { @@ -1090,12 +1090,12 @@ impl<'a> Writer<'a> { fn winrt_produce_type(&self, param: &SignatureParam, include_param_names: bool) -> TokenStream { let default_type = self.type_default_name(¶m.ty); - let sig = if self.reader.param_flags(param.def).contains(ParamAttributes::In) { + let sig = if param.def.flags().contains(ParamAttributes::In) { if param.ty.is_winrt_array() { quote! { &[#default_type] } - } else if type_is_primitive(self.reader, ¶m.ty) { + } else if type_is_primitive(¶m.ty) { quote! { #default_type } - } else if type_is_nullable(self.reader, ¶m.ty) { + } else if type_is_nullable(¶m.ty) { let type_name = self.type_name(¶m.ty); quote! { ::core::option::Option<&#type_name> } } else { @@ -1121,10 +1121,10 @@ impl<'a> Writer<'a> { let name = self.param_name(param.def); let kind = self.type_default_name(¶m.ty); - if self.reader.param_flags(param.def).contains(ParamAttributes::In) { - if type_is_primitive(self.reader, ¶m.ty) { + if param.def.flags().contains(ParamAttributes::In) { + if type_is_primitive(¶m.ty) { quote! { #name: #kind, } - } else if type_is_nullable(self.reader, ¶m.ty) { + } else if type_is_nullable(¶m.ty) { let kind = self.type_name(¶m.ty); quote! { #name: ::core::option::Option<&#kind>, } } else { @@ -1181,8 +1181,8 @@ fn gen_const_ptrs(pointers: usize) -> TokenStream { "*const ".repeat(pointers).into() } -fn type_def_async_kind(reader: &Reader, row: TypeDef) -> AsyncKind { - match reader.type_def_type_name(row) { +fn type_def_async_kind(row: TypeDef) -> AsyncKind { + match row.type_name() { TypeName::IAsyncAction => AsyncKind::Action, TypeName::IAsyncActionWithProgress => AsyncKind::ActionWithProgress, TypeName::IAsyncOperation => AsyncKind::Operation, @@ -1191,12 +1191,12 @@ fn type_def_async_kind(reader: &Reader, row: TypeDef) -> AsyncKind { } } -fn type_def_is_agile(reader: &Reader, row: TypeDef) -> bool { - for attribute in reader.attributes(row) { - match reader.attribute_name(attribute) { +fn type_def_is_agile(row: TypeDef) -> bool { + for attribute in row.attributes() { + match attribute.name() { "AgileAttribute" => return true, "MarshalingBehaviorAttribute" => { - if let Some((_, Value::EnumDef(_, value))) = reader.attribute_args(attribute).get(0) { + if let Some((_, Value::EnumDef(_, value))) = attribute.args().get(0) { if let Value::I32(2) = **value { return true; } @@ -1205,7 +1205,7 @@ fn type_def_is_agile(reader: &Reader, row: TypeDef) -> bool { _ => {} } } - matches!(reader.type_def_type_name(row), TypeName::IAsyncAction | TypeName::IAsyncActionWithProgress | TypeName::IAsyncOperation | TypeName::IAsyncOperationWithProgress) + matches!(row.type_name(), TypeName::IAsyncAction | TypeName::IAsyncActionWithProgress | TypeName::IAsyncOperation | TypeName::IAsyncOperationWithProgress) } #[cfg(test)]