From 22de1c9640032c31cd7b82c7376d60122d17f776 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 18 Oct 2023 13:47:46 -0500 Subject: [PATCH] Simplify metadata filtering (#2684) --- crates/libs/bindgen/src/lib.rs | 11 +- crates/libs/bindgen/src/metadata.rs | 135 +++++++++--------- crates/libs/bindgen/src/rdl/from_reader.rs | 19 ++- crates/libs/bindgen/src/rust/cfg.rs | 76 +++++----- crates/libs/bindgen/src/rust/classes.rs | 12 +- crates/libs/bindgen/src/rust/com_methods.rs | 4 +- crates/libs/bindgen/src/rust/constants.rs | 2 +- crates/libs/bindgen/src/rust/delegates.rs | 8 +- crates/libs/bindgen/src/rust/enums.rs | 4 +- crates/libs/bindgen/src/rust/functions.rs | 8 +- crates/libs/bindgen/src/rust/handles.rs | 6 +- crates/libs/bindgen/src/rust/implements.rs | 8 +- crates/libs/bindgen/src/rust/interfaces.rs | 10 +- crates/libs/bindgen/src/rust/iterators.rs | 8 +- crates/libs/bindgen/src/rust/mod.rs | 14 +- crates/libs/bindgen/src/rust/standalone.rs | 46 +++--- crates/libs/bindgen/src/rust/structs.rs | 20 +-- crates/libs/bindgen/src/rust/winrt_methods.rs | 22 +-- crates/libs/bindgen/src/rust/writer.rs | 14 +- crates/libs/bindgen/src/tree.rs | 4 +- crates/libs/bindgen/src/winmd/from_reader.rs | 4 +- crates/libs/bindgen/src/winmd/verify.rs | 6 +- crates/libs/metadata/src/filter.rs | 42 ++---- crates/libs/metadata/src/lib.rs | 4 +- crates/libs/metadata/src/reader.rs | 26 +++- crates/tests/metadata/tests/attribute_enum.rs | 2 +- crates/tests/metadata/tests/fn_call_size.rs | 2 +- crates/tests/metadata/tests/unused.rs | 6 +- crates/tests/riddle/tests/composition.rs | 3 +- .../tests/riddle/tests/generic_interfaces.rs | 4 +- crates/tests/riddle/tests/nested_module.rs | 8 +- crates/tools/lib/src/lib.rs | 6 +- 32 files changed, 264 insertions(+), 280 deletions(-) diff --git a/crates/libs/bindgen/src/lib.rs b/crates/libs/bindgen/src/lib.rs index b52c42dbce..1ab31d442e 100644 --- a/crates/libs/bindgen/src/lib.rs +++ b/crates/libs/bindgen/src/lib.rs @@ -104,15 +104,14 @@ where let output = canonicalize(output)?; let input = read_input(&input)?; - let reader = metadata::Reader::new(input); - let filter = metadata::Filter::new(&include, &exclude); + let reader = metadata::Reader::filter(input, &include, &exclude); - winmd::verify(reader, &filter)?; + winmd::verify(reader)?; match extension(&output) { - "rdl" => rdl::from_reader(reader, &filter, config, &output)?, - "winmd" => winmd::from_reader(reader, &filter, config, &output)?, - "rs" => rust::from_reader(reader, &filter, config, &output)?, + "rdl" => rdl::from_reader(reader, config, &output)?, + "winmd" => winmd::from_reader(reader, config, &output)?, + "rs" => rust::from_reader(reader, config, &output)?, _ => return Err(Error::new("output extension must be one of winmd/rdl/rs")), } diff --git a/crates/libs/bindgen/src/metadata.rs b/crates/libs/bindgen/src/metadata.rs index 7c8a55ec1b..994cba7f7b 100644 --- a/crates/libs/bindgen/src/metadata.rs +++ b/crates/libs/bindgen/src/metadata.rs @@ -123,7 +123,8 @@ pub fn type_def_generics(def: TypeDef) -> Vec { // TODO: namespace should not be required - it's a hack to accomodate Win32 metadata // TODO: this is very Rust-specific and Win32-metadata specific with all of its translation. Replace with literal signature parser that just returns slice of types. -pub fn method_def_signature(reader: &Reader, namespace: &str, row: MethodDef, generics: &[Type]) -> Signature { +pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type]) -> Signature { + let reader = row.reader(); let mut blob = row.blob(4); let call_flags = MethodCallAttributes(blob.read_usize() as u8); let _param_count = blob.read_usize(); @@ -213,7 +214,7 @@ pub fn method_def_signature(reader: &Reader, namespace: &str, row: MethodDef, ge for param in &mut params { if param.kind == SignatureParamKind::Other { - if signature_param_is_convertible(reader, param) { + if signature_param_is_convertible(param) { if type_is_non_exclusive_winrt_interface(¶m.ty) { param.kind = SignatureParamKind::TryInto; } else { @@ -223,9 +224,9 @@ pub fn method_def_signature(reader: &Reader, namespace: &str, row: MethodDef, ge let flags = param.def.flags(); if param.ty.is_pointer() && (flags.contains(ParamAttributes::Optional) || param.def.has_attribute("ReservedAttribute")) { param.kind = SignatureParamKind::OptionalPointer; - } else if type_is_primitive(¶m.ty) && (!param.ty.is_pointer() || type_is_blittable(reader, ¶m.ty.deref())) { + } else if type_is_primitive(¶m.ty) && (!param.ty.is_pointer() || type_is_blittable(¶m.ty.deref())) { param.kind = SignatureParamKind::ValueType; - } else if type_is_blittable(reader, ¶m.ty) { + } else if type_is_blittable(¶m.ty) { param.kind = SignatureParamKind::Blittable; } } @@ -272,8 +273,8 @@ fn param_or_enum(row: Param) -> Option { }) } -pub fn signature_param_is_convertible(reader: &Reader, param: &SignatureParam) -> bool { - !param.def.flags().contains(ParamAttributes::Out) && !param.ty.is_winrt_array() && !param.ty.is_pointer() && !param.kind.is_array() && (type_is_borrowed(reader, ¶m.ty) || type_is_non_exclusive_winrt_interface(¶m.ty) || type_is_trivially_convertible(¶m.ty)) +pub fn signature_param_is_convertible(param: &SignatureParam) -> bool { + !param.def.flags().contains(ParamAttributes::Out) && !param.ty.is_winrt_array() && !param.ty.is_pointer() && !param.kind.is_array() && (type_is_borrowed(¶m.ty) || type_is_non_exclusive_winrt_interface(¶m.ty) || type_is_trivially_convertible(¶m.ty)) } fn signature_param_is_retval(param: &SignatureParam) -> bool { @@ -363,9 +364,9 @@ fn method_def_last_error(row: MethodDef) -> bool { } } -pub fn type_is_borrowed(reader: &Reader, ty: &Type) -> bool { +pub fn type_is_borrowed(ty: &Type) -> bool { match ty { - Type::TypeDef(row, _) => !type_def_is_blittable(reader, *row), + Type::TypeDef(row, _) => !type_def_is_blittable(*row), Type::BSTR | Type::PCSTR | Type::PCWSTR | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => true, _ => false, } @@ -403,32 +404,32 @@ fn type_def_is_callback(row: TypeDef) -> bool { !row.flags().contains(TypeAttributes::WindowsRuntime) && row.kind() == TypeKind::Delegate } -pub fn type_has_callback(reader: &Reader, ty: &Type) -> bool { +pub fn type_has_callback(ty: &Type) -> bool { match ty { - Type::TypeDef(row, _) => type_def_has_callback(reader, *row), - Type::Win32Array(ty, _) => type_has_callback(reader, ty), + Type::TypeDef(row, _) => type_def_has_callback(*row), + Type::Win32Array(ty, _) => type_has_callback(ty), _ => false, } } -pub fn type_def_has_callback(reader: &Reader, row: TypeDef) -> bool { +pub fn type_def_has_callback(row: TypeDef) -> bool { if type_def_is_callback(row) { return true; } if row.kind() != TypeKind::Struct { return false; } - fn check(reader: &Reader, row: TypeDef) -> bool { - if row.fields().any(|field| type_has_callback(reader, &field.ty(Some(row)))) { + fn check(row: TypeDef) -> bool { + if row.fields().any(|field| type_has_callback(&field.ty(Some(row)))) { return true; } false } let type_name = row.type_name(); if type_name.namespace.is_empty() { - check(reader, row) + check(row) } else { - for row in reader.get_type_def(type_name.namespace, type_name.name) { - if check(reader, row) { + for row in row.reader().get_type_def(type_name.namespace, type_name.name) { + if check(row) { return true; } } @@ -436,7 +437,7 @@ pub fn type_def_has_callback(reader: &Reader, row: TypeDef) -> bool { } } -pub fn type_interfaces(reader: &Reader, ty: &Type) -> Vec { +pub fn type_interfaces(ty: &Type) -> Vec { // TODO: collect into btree map and then return collected vec // This will both sort the results and should make finding dupes faster fn walk(result: &mut Vec, parent: &Type, is_base: bool) { @@ -473,7 +474,7 @@ pub fn type_interfaces(reader: &Reader, ty: &Type) -> Vec { walk(&mut result, ty, false); if let Type::TypeDef(row, _) = ty { if row.kind() == TypeKind::Class { - for base in type_def_bases(reader, *row) { + for base in type_def_bases(*row) { walk(&mut result, &Type::TypeDef(base, Vec::new()), true); } for attribute in row.attributes() { @@ -482,7 +483,7 @@ pub fn type_interfaces(reader: &Reader, ty: &Type) -> Vec { for (_, arg) in attribute.args() { if let Value::TypeName(type_name) = arg { let type_name = parse_type_name(&type_name); - let def = reader.get_type_def(type_name.0, type_name.1).next().expect("Type not found"); + let def = row.reader().get_type_def(type_name.0, type_name.1).next().expect("Type not found"); result.push(Interface { ty: Type::TypeDef(def, Vec::new()), kind: InterfaceKind::Static }); break; } @@ -504,39 +505,39 @@ fn type_name<'a>(ty: &Type) -> &'a str { } } -pub fn field_is_blittable(reader: &Reader, row: Field, enclosing: TypeDef) -> bool { - type_is_blittable(reader, &row.ty(Some(enclosing))) +pub fn field_is_blittable(row: Field, enclosing: TypeDef) -> bool { + type_is_blittable(&row.ty(Some(enclosing))) } -pub fn field_is_copyable(reader: &Reader, row: Field, enclosing: TypeDef) -> bool { - type_is_copyable(reader, &row.ty(Some(enclosing))) +pub fn field_is_copyable(row: Field, enclosing: TypeDef) -> bool { + type_is_copyable(&row.ty(Some(enclosing))) } -pub fn type_is_blittable(reader: &Reader, ty: &Type) -> bool { +pub fn type_is_blittable(ty: &Type) -> bool { match ty { - Type::TypeDef(row, _) => type_def_is_blittable(reader, *row), + Type::TypeDef(row, _) => type_def_is_blittable(*row), Type::String | Type::BSTR | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => false, - Type::Win32Array(kind, _) => type_is_blittable(reader, kind), - Type::WinrtArray(kind) => type_is_blittable(reader, kind), + Type::Win32Array(kind, _) => type_is_blittable(kind), + Type::WinrtArray(kind) => type_is_blittable(kind), _ => true, } } -fn type_is_copyable(reader: &Reader, ty: &Type) -> bool { +fn type_is_copyable(ty: &Type) -> bool { match ty { - Type::TypeDef(row, _) => type_def_is_copyable(reader, *row), + Type::TypeDef(row, _) => type_def_is_copyable(*row), Type::String | Type::BSTR | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => false, - Type::Win32Array(kind, _) => type_is_copyable(reader, kind), - Type::WinrtArray(kind) => type_is_copyable(reader, kind), + Type::Win32Array(kind, _) => type_is_copyable(kind), + Type::WinrtArray(kind) => type_is_copyable(kind), _ => true, } } -pub fn type_def_is_blittable(reader: &Reader, row: TypeDef) -> bool { +pub fn type_def_is_blittable(row: TypeDef) -> bool { match row.kind() { TypeKind::Struct => { if row.flags().contains(TypeAttributes::WindowsRuntime) { - row.fields().all(|field| field_is_blittable(reader, field, row)) + row.fields().all(|field| field_is_blittable(field, row)) } else { true } @@ -547,9 +548,9 @@ pub fn type_def_is_blittable(reader: &Reader, row: TypeDef) -> bool { } } -pub fn type_def_is_copyable(reader: &Reader, row: TypeDef) -> bool { +pub fn type_def_is_copyable(row: TypeDef) -> bool { match row.kind() { - TypeKind::Struct => row.fields().all(|field| field_is_copyable(reader, field, row)), + TypeKind::Struct => row.fields().all(|field| field_is_copyable(field, row)), TypeKind::Enum => true, TypeKind::Delegate => !row.flags().contains(TypeAttributes::WindowsRuntime), _ => false, @@ -588,33 +589,33 @@ pub fn type_is_primitive(ty: &Type) -> bool { } } -fn type_has_explicit_layout(reader: &Reader, ty: &Type) -> bool { +fn type_has_explicit_layout(ty: &Type) -> bool { match ty { - Type::TypeDef(row, _) => type_def_has_explicit_layout(reader, *row), - Type::Win32Array(ty, _) => type_has_explicit_layout(reader, ty), + Type::TypeDef(row, _) => type_def_has_explicit_layout(*row), + Type::Win32Array(ty, _) => type_has_explicit_layout(ty), _ => false, } } -pub fn type_def_has_explicit_layout(reader: &Reader, row: TypeDef) -> bool { +pub fn type_def_has_explicit_layout(row: TypeDef) -> bool { if row.kind() != TypeKind::Struct { return false; } - fn check(reader: &Reader, row: TypeDef) -> bool { + fn check(row: TypeDef) -> bool { if row.flags().contains(TypeAttributes::ExplicitLayout) { return true; } - if row.fields().any(|field| type_has_explicit_layout(reader, &field.ty(Some(row)))) { + if row.fields().any(|field| type_has_explicit_layout(&field.ty(Some(row)))) { return true; } false } let type_name = row.type_name(); if type_name.namespace.is_empty() { - check(reader, row) + check(row) } else { - for row in reader.get_type_def(type_name.namespace, type_name.name) { - if check(reader, row) { + for row in row.reader().get_type_def(type_name.namespace, type_name.name) { + if check(row) { return true; } } @@ -622,33 +623,33 @@ pub fn type_def_has_explicit_layout(reader: &Reader, row: TypeDef) -> bool { } } -fn type_has_packing(reader: &Reader, ty: &Type) -> bool { +fn type_has_packing(ty: &Type) -> bool { match ty { - Type::TypeDef(row, _) => type_def_has_packing(reader, *row), - Type::Win32Array(ty, _) => type_has_packing(reader, ty), + Type::TypeDef(row, _) => type_def_has_packing(*row), + Type::Win32Array(ty, _) => type_has_packing(ty), _ => false, } } -pub fn type_def_has_packing(reader: &Reader, row: TypeDef) -> bool { +pub fn type_def_has_packing(row: TypeDef) -> bool { if row.kind() != TypeKind::Struct { return false; } - fn check(reader: &Reader, row: TypeDef) -> bool { + fn check(row: TypeDef) -> bool { if row.class_layout().is_some() { return true; } - if row.fields().any(|field| type_has_packing(reader, &field.ty(Some(row)))) { + if row.fields().any(|field| type_has_packing(&field.ty(Some(row)))) { return true; } false } let type_name = row.type_name(); if type_name.namespace.is_empty() { - check(reader, row) + check(row) } else { - for row in reader.get_type_def(type_name.namespace, type_name.name) { - if check(reader, row) { + for row in row.reader().get_type_def(type_name.namespace, type_name.name) { + if check(row) { return true; } } @@ -660,7 +661,7 @@ pub fn type_def_default_interface(row: TypeDef) -> Option { row.interface_impls().find_map(move |row| if row.has_attribute("DefaultAttribute") { Some(row.ty(&[])) } else { None }) } -fn type_signature(reader: &Reader, ty: &Type) -> String { +fn type_signature(ty: &Type) -> String { match ty { Type::Bool => "b1".to_string(), Type::Char => "c2".to_string(), @@ -680,42 +681,42 @@ fn type_signature(reader: &Reader, ty: &Type) -> String { Type::IInspectable => "cinterface(IInspectable)".to_string(), Type::GUID => "g16".to_string(), Type::HRESULT => "struct(Windows.Foundation.HResult;i4)".to_string(), - Type::TypeDef(row, generics) => type_def_signature(reader, *row, generics), + Type::TypeDef(row, generics) => type_def_signature(*row, generics), rest => unimplemented!("{rest:?}"), } } -pub fn type_def_signature(reader: &Reader, row: TypeDef, generics: &[Type]) -> String { +pub fn type_def_signature(row: TypeDef, generics: &[Type]) -> String { match row.kind() { - TypeKind::Interface => type_def_interface_signature(reader, row, generics), + TypeKind::Interface => type_def_interface_signature(row, generics), TypeKind::Class => { if let Some(Type::TypeDef(default, generics)) = type_def_default_interface(row) { - format!("rc({};{})", row.type_name(), type_def_interface_signature(reader, default, &generics)) + format!("rc({};{})", row.type_name(), type_def_interface_signature(default, &generics)) } else { unimplemented!(); } } - TypeKind::Enum => format!("enum({};{})", row.type_name(), type_signature(reader, &row.underlying_type())), + TypeKind::Enum => format!("enum({};{})", row.type_name(), type_signature(&row.underlying_type())), TypeKind::Struct => { let mut result = format!("struct({}", row.type_name()); for field in row.fields() { result.push(';'); - result.push_str(&type_signature(reader, &field.ty(Some(row)))); + result.push_str(&type_signature(&field.ty(Some(row)))); } result.push(')'); result } TypeKind::Delegate => { if generics.is_empty() { - format!("delegate({})", type_def_interface_signature(reader, row, generics)) + format!("delegate({})", type_def_interface_signature(row, generics)) } else { - type_def_interface_signature(reader, row, generics) + type_def_interface_signature(row, generics) } } } } -fn type_def_interface_signature(reader: &Reader, row: TypeDef, generics: &[Type]) -> String { +fn type_def_interface_signature(row: TypeDef, generics: &[Type]) -> String { let guid = type_def_guid(row).unwrap(); if generics.is_empty() { format!("{{{guid:#?}}}") @@ -723,7 +724,7 @@ fn type_def_interface_signature(reader: &Reader, row: TypeDef, generics: &[Type] let mut result = format!("pinterface({{{guid:#?}}}"); for generic in generics { result.push(';'); - result.push_str(&type_signature(reader, generic)); + result.push_str(&type_signature(generic)); } result.push(')'); result @@ -738,12 +739,12 @@ pub fn type_def_guid(row: TypeDef) -> Option { row.find_attribute("GuidAttribute").map(|attribute| Guid::from_args(&attribute.args())) } -pub fn type_def_bases(reader: &Reader, mut row: TypeDef) -> Vec { +pub fn type_def_bases(mut row: TypeDef) -> Vec { let mut bases = Vec::new(); loop { match row.extends() { Some(base) if base != TypeName::Object => { - row = reader.get_type_def(base.namespace, base.name).next().expect("Type not found"); + row = row.reader().get_type_def(base.namespace, base.name).next().expect("Type not found"); bases.push(row); } _ => break, diff --git a/crates/libs/bindgen/src/rdl/from_reader.rs b/crates/libs/bindgen/src/rdl/from_reader.rs index 59b4543ba2..3842614fc2 100644 --- a/crates/libs/bindgen/src/rdl/from_reader.rs +++ b/crates/libs/bindgen/src/rdl/from_reader.rs @@ -3,14 +3,14 @@ use crate::tokens::{quote, to_ident, TokenStream}; use crate::{rdl, Error, Result, Tree}; use metadata::*; -pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { +pub fn from_reader(reader: &metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { let dialect = match config.remove("type") { Some("winrt") => Dialect::WinRT, Some("win32") => Dialect::Win32, _ => return Err(Error::new("configuration value `type` must be `win32` or `winrt`")), }; - let mut writer = Writer::new(reader, filter, output, dialect); + let mut writer = Writer::new(reader, output, dialect); // TODO: be sure to use the same "split" key for winmd splitting. // May also want to support split=N similar to the way MIDLRT supports winmd splitting @@ -29,7 +29,7 @@ pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, mut con } fn gen_split(writer: &Writer) -> Result<()> { - let tree = Tree::new(writer.reader, writer.filter); + let tree = Tree::new(writer.reader); let directory = crate::directory(writer.output); // TODO: parallelize @@ -46,7 +46,7 @@ fn gen_split(writer: &Writer) -> Result<()> { } fn gen_file(writer: &Writer) -> Result<()> { - let tree = Tree::new(writer.reader, writer.filter); + let tree = Tree::new(writer.reader); let tokens = writer.tree(&tree); writer.write_to_file(writer.output, tokens) } @@ -59,7 +59,6 @@ enum Dialect { struct Writer<'a> { reader: &'a metadata::Reader, - filter: &'a metadata::Filter<'a>, namespace: &'a str, dialect: Dialect, split: bool, @@ -67,12 +66,12 @@ struct Writer<'a> { } impl<'a> Writer<'a> { - fn new(reader: &'a metadata::Reader, filter: &'a metadata::Filter, output: &'a str, dialect: Dialect) -> Self { - Self { reader, filter, namespace: "", output, dialect, split: false } + fn new(reader: &'a metadata::Reader, output: &'a str, dialect: Dialect) -> Self { + Self { reader, namespace: "", output, dialect, split: false } } fn with_namespace(&self, namespace: &'a str) -> Self { - Self { reader: self.reader, filter: self.filter, namespace, dialect: self.dialect, output: self.output, split: self.split } + Self { reader: self.reader, namespace, dialect: self.dialect, output: self.output, split: self.split } } fn write_to_file(&self, output: &str, tokens: TokenStream) -> Result<()> { @@ -135,7 +134,7 @@ impl<'a> Writer<'a> { let mut types = vec![]; if !tree.namespace.is_empty() { - for item in self.reader.namespace_items(tree.namespace, self.filter).filter(|item| match item { + for item in self.reader.namespace_items(tree.namespace).filter(|item| match item { metadata::Item::Type(def) => { let winrt = def.flags().contains(metadata::TypeAttributes::WindowsRuntime); match self.dialect { @@ -246,7 +245,7 @@ impl<'a> Writer<'a> { let name = to_ident(method.name()); // TODO: use reader.method_def_signature instead - let signature = metadata::method_def_signature(self.reader, def.namespace(), method, generics); + let signature = metadata::method_def_signature(def.namespace(), method, generics); let return_type = self.return_type(&signature.return_type); diff --git a/crates/libs/bindgen/src/rust/cfg.rs b/crates/libs/bindgen/src/rust/cfg.rs index 5e4a820831..59989f08a0 100644 --- a/crates/libs/bindgen/src/rust/cfg.rs +++ b/crates/libs/bindgen/src/rust/cfg.rs @@ -1,15 +1,15 @@ use super::*; #[derive(Default, Clone)] -pub struct Cfg<'a> { - pub types: BTreeMap<&'a str, BTreeSet>, +pub struct Cfg { + pub types: BTreeMap<&'static str, BTreeSet>, pub core_types: BTreeSet, pub arches: BTreeSet<&'static str>, pub implement: bool, } -impl<'a> Cfg<'a> { - pub fn add_feature(&mut self, feature: &'a str) { +impl Cfg { + pub fn add_feature(&mut self, feature: &'static str) { self.types.entry(feature).or_default(); } pub fn union(&self, other: &Self) -> Self { @@ -30,44 +30,44 @@ impl<'a> Cfg<'a> { } } -pub fn field_cfg(reader: &Reader, row: Field) -> Cfg { +pub fn field_cfg(row: Field) -> Cfg { let mut cfg = Cfg::default(); - field_cfg_combine(reader, row, None, &mut cfg); + field_cfg_combine(row, None, &mut cfg); cfg } -fn field_cfg_combine<'a>(reader: &'a Reader, row: Field, enclosing: Option, cfg: &mut Cfg<'a>) { - type_cfg_combine(reader, &row.ty(enclosing), cfg) +fn field_cfg_combine(row: Field, enclosing: Option, cfg: &mut Cfg) { + type_cfg_combine(&row.ty(enclosing), cfg) } -pub fn type_def_cfg<'a>(reader: &'a Reader, row: TypeDef, generics: &[Type]) -> Cfg<'a> { +pub fn type_def_cfg(row: TypeDef, generics: &[Type]) -> Cfg { let mut cfg = Cfg::default(); - type_def_cfg_combine(reader, row, generics, &mut cfg); + type_def_cfg_combine(row, generics, &mut cfg); cfg_add_attributes(&mut cfg, row); cfg } -pub fn type_def_cfg_impl<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type]) -> Cfg<'a> { +pub fn type_def_cfg_impl(def: TypeDef, generics: &[Type]) -> Cfg { let mut cfg = Cfg { implement: true, ..Default::default() }; - fn combine<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) { - type_def_cfg_combine(reader, def, generics, cfg); + fn combine(def: TypeDef, generics: &[Type], cfg: &mut Cfg) { + type_def_cfg_combine(def, generics, cfg); for method in def.methods() { - signature_cfg_combine(reader, &method.signature(generics), cfg); + signature_cfg_combine(&method.signature(generics), cfg); } } - combine(reader, def, generics, &mut cfg); + combine(def, generics, &mut cfg); for def in type_def_vtables(def) { if let Type::TypeDef(def, generics) = def { - combine(reader, def, &generics, &mut cfg); + combine(def, &generics, &mut cfg); } } if def.flags().contains(TypeAttributes::WindowsRuntime) { for interface in type_def_interfaces(def, generics) { if let Type::TypeDef(def, generics) = interface { - combine(reader, def, &generics, &mut cfg); + combine(def, &generics, &mut cfg); } } } @@ -75,18 +75,18 @@ pub fn type_def_cfg_impl<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type] cfg_add_attributes(&mut cfg, def); cfg } -pub fn type_def_cfg_combine<'a>(reader: &'a Reader, row: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) { +pub fn type_def_cfg_combine(row: TypeDef, generics: &[Type], cfg: &mut Cfg) { let type_name = row.type_name(); for generic in generics { - type_cfg_combine(reader, generic, cfg); + type_cfg_combine(generic, cfg); } if cfg.types.entry(type_name.namespace).or_default().insert(row) { match row.kind() { TypeKind::Class => { if let Some(default_interface) = type_def_default_interface(row) { - type_cfg_combine(reader, &default_interface, cfg); + type_cfg_combine(&default_interface, cfg); } } TypeKind::Interface => { @@ -99,30 +99,30 @@ pub fn type_def_cfg_combine<'a>(reader: &'a Reader, row: TypeDef, generics: &[Ty } } TypeKind::Struct => { - row.fields().for_each(|field| field_cfg_combine(reader, field, Some(row), cfg)); + row.fields().for_each(|field| field_cfg_combine(field, Some(row), cfg)); if !type_name.namespace.is_empty() { - for def in reader.get_type_def(type_name.namespace, type_name.name) { + for def in row.reader().get_type_def(type_name.namespace, type_name.name) { if def != row { - type_def_cfg_combine(reader, def, &[], cfg); + type_def_cfg_combine(def, &[], cfg); } } } } - TypeKind::Delegate => signature_cfg_combine(reader, &type_def_invoke_method(row).signature(generics), cfg), + TypeKind::Delegate => signature_cfg_combine(&type_def_invoke_method(row).signature(generics), cfg), _ => {} } } } -pub fn signature_cfg(reader: &Reader, method: MethodDef) -> Cfg { +pub fn signature_cfg(method: MethodDef) -> Cfg { let mut cfg = Cfg::default(); - signature_cfg_combine(reader, &method.signature(&[]), &mut cfg); + signature_cfg_combine(&method.signature(&[]), &mut cfg); cfg_add_attributes(&mut cfg, method); cfg } -fn signature_cfg_combine<'a>(reader: &'a Reader, signature: &MethodDefSig, cfg: &mut Cfg<'a>) { - type_cfg_combine(reader, &signature.return_type, cfg); - signature.params.iter().for_each(|param| type_cfg_combine(reader, param, cfg)); +fn signature_cfg_combine(signature: &MethodDefSig, cfg: &mut Cfg) { + type_cfg_combine(&signature.return_type, cfg); + signature.params.iter().for_each(|param| type_cfg_combine(param, cfg)); } fn cfg_add_attributes>(cfg: &mut Cfg, row: R) { @@ -151,19 +151,19 @@ fn cfg_add_attributes>(cfg: &mut Cfg, row: R) { } } -pub fn type_cfg<'a>(reader: &'a Reader, ty: &Type) -> Cfg<'a> { +pub fn type_cfg(ty: &Type) -> Cfg { let mut cfg = Cfg::default(); - type_cfg_combine(reader, ty, &mut cfg); + type_cfg_combine(ty, &mut cfg); cfg } -fn type_cfg_combine<'a>(reader: &'a Reader, ty: &Type, cfg: &mut Cfg<'a>) { +fn type_cfg_combine(ty: &Type, cfg: &mut Cfg) { match ty { - Type::TypeDef(row, generics) => type_def_cfg_combine(reader, *row, generics, cfg), - Type::Win32Array(ty, _) => type_cfg_combine(reader, ty, cfg), - Type::ConstPtr(ty, _) => type_cfg_combine(reader, ty, cfg), - Type::MutPtr(ty, _) => type_cfg_combine(reader, ty, cfg), - Type::WinrtArray(ty) => type_cfg_combine(reader, ty, cfg), - Type::WinrtArrayRef(ty) => type_cfg_combine(reader, ty, cfg), + Type::TypeDef(row, generics) => type_def_cfg_combine(*row, generics, cfg), + Type::Win32Array(ty, _) => type_cfg_combine(ty, cfg), + Type::ConstPtr(ty, _) => type_cfg_combine(ty, cfg), + Type::MutPtr(ty, _) => type_cfg_combine(ty, cfg), + Type::WinrtArray(ty) => type_cfg_combine(ty, cfg), + Type::WinrtArrayRef(ty) => type_cfg_combine(ty, cfg), ty => _ = cfg.core_types.insert(ty.clone()), } } diff --git a/crates/libs/bindgen/src/rust/classes.rs b/crates/libs/bindgen/src/rust/classes.rs index 2ff96ef1f2..865b6734fb 100644 --- a/crates/libs/bindgen/src/rust/classes.rs +++ b/crates/libs/bindgen/src/rust/classes.rs @@ -21,11 +21,11 @@ fn gen_class(writer: &Writer, def: TypeDef) -> TokenStream { } let name = to_ident(def.name()); - let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, Vec::new())); + let interfaces = type_interfaces(&Type::TypeDef(def, Vec::new())); let mut methods = quote! {}; let mut method_names = MethodNames::new(); - let cfg = type_def_cfg(writer.reader, def, &[]); + let cfg = type_def_cfg(def, &[]); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); @@ -44,7 +44,7 @@ fn gen_class(writer: &Writer, def: TypeDef) -> TokenStream { if let Type::TypeDef(def, generics) = &interface.ty { if def.methods().next().is_some() { let interface_type = writer.type_name(&interface.ty); - let features = writer.cfg_features(&type_def_cfg(writer.reader, *def, generics)); + let features = writer.cfg_features(&type_def_cfg(*def, generics)); return Some(quote! { #[doc(hidden)] @@ -138,7 +138,7 @@ fn gen_conversions(writer: &Writer, def: TypeDef, name: &TokenStream, interfaces } let into = writer.type_name(&interface.ty); - let features = writer.cfg_features(&cfg.union(&type_cfg(writer.reader, &interface.ty))); + let features = writer.cfg_features(&cfg.union(&type_cfg(&interface.ty))); tokens.combine("e! { #features @@ -146,9 +146,9 @@ fn gen_conversions(writer: &Writer, def: TypeDef, name: &TokenStream, interfaces }); } - for def in type_def_bases(writer.reader, def) { + for def in type_def_bases(def) { let into = writer.type_def_name(def, &[]); - let features = writer.cfg_features(&cfg.union(&type_def_cfg(writer.reader, def, &[]))); + let features = writer.cfg_features(&cfg.union(&type_def_cfg(def, &[]))); tokens.combine("e! { #features diff --git a/crates/libs/bindgen/src/rust/com_methods.rs b/crates/libs/bindgen/src/rust/com_methods.rs index 4a0b0374c0..22c8fef7db 100644 --- a/crates/libs/bindgen/src/rust/com_methods.rs +++ b/crates/libs/bindgen/src/rust/com_methods.rs @@ -1,13 +1,13 @@ use super::*; pub fn writer(writer: &Writer, def: TypeDef, kind: InterfaceKind, method: MethodDef, method_names: &mut MethodNames, virtual_names: &mut MethodNames, base_count: usize) -> TokenStream { - let signature = method_def_signature(writer.reader, def.namespace(), method, &[]); + let signature = method_def_signature(def.namespace(), method, &[]); let name = method_names.add(method); let vname = virtual_names.add(method); let generics = writer.constraint_generics(&signature.params); let where_clause = writer.where_clause(&signature.params); - let mut cfg = signature_cfg(writer.reader, method); + let mut cfg = signature_cfg(method); cfg.add_feature(def.namespace()); let doc = writer.cfg_method_doc(&cfg); let features = writer.cfg_features(&cfg); diff --git a/crates/libs/bindgen/src/rust/constants.rs b/crates/libs/bindgen/src/rust/constants.rs index d4ade7b3a9..1f15c4c291 100644 --- a/crates/libs/bindgen/src/rust/constants.rs +++ b/crates/libs/bindgen/src/rust/constants.rs @@ -3,7 +3,7 @@ use super::*; pub fn writer(writer: &Writer, def: Field) -> TokenStream { let name = to_ident(def.name()); let ty = def.ty(None).to_const_type(); - let cfg = field_cfg(writer.reader, def); + let cfg = field_cfg(def); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); diff --git a/crates/libs/bindgen/src/rust/delegates.rs b/crates/libs/bindgen/src/rust/delegates.rs index 01d79a1166..479d8db622 100644 --- a/crates/libs/bindgen/src/rust/delegates.rs +++ b/crates/libs/bindgen/src/rust/delegates.rs @@ -12,10 +12,10 @@ fn gen_callback(writer: &Writer, def: TypeDef) -> TokenStream { let name = to_ident(def.name()); let method = type_def_invoke_method(def); - let signature = method_def_signature(writer.reader, def.namespace(), method, &[]); + let signature = method_def_signature(def.namespace(), method, &[]); let return_type = writer.return_sig(&signature); - let cfg = type_def_cfg(writer.reader, def, &[]); + let cfg = type_def_cfg(def, &[]); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); @@ -57,10 +57,10 @@ fn gen_win_delegate(writer: &Writer, def: TypeDef) -> TokenStream { let ident = writer.type_def_name(def, generics); let method = type_def_invoke_method(def); - let signature = method_def_signature(writer.reader, def.namespace(), method, generics); + let signature = method_def_signature(def.namespace(), method, generics); let fn_constraint = gen_fn_constraint(writer, def, &signature); - let cfg = type_def_cfg(writer.reader, def, generics); + let cfg = type_def_cfg(def, generics); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); diff --git a/crates/libs/bindgen/src/rust/enums.rs b/crates/libs/bindgen/src/rust/enums.rs index ad4b677fa0..3039aebd0a 100644 --- a/crates/libs/bindgen/src/rust/enums.rs +++ b/crates/libs/bindgen/src/rust/enums.rs @@ -9,7 +9,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { // TODO: unscoped enums should be removed from metadata let is_scoped = def.flags().contains(TypeAttributes::WindowsRuntime) || def.has_attribute("ScopedEnumAttribute"); - let cfg = type_def_cfg(writer.reader, def, &[]); + let cfg = type_def_cfg(def, &[]); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); @@ -160,7 +160,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { } if def.flags().contains(TypeAttributes::WindowsRuntime) { - let signature = Literal::byte_string(type_def_signature(writer.reader, def, &[]).as_bytes()); + let signature = Literal::byte_string(type_def_signature(def, &[]).as_bytes()); tokens.combine("e! { #features diff --git a/crates/libs/bindgen/src/rust/functions.rs b/crates/libs/bindgen/src/rust/functions.rs index f0e79bbf75..304974c595 100644 --- a/crates/libs/bindgen/src/rust/functions.rs +++ b/crates/libs/bindgen/src/rust/functions.rs @@ -21,8 +21,8 @@ pub fn writer(writer: &Writer, namespace: &str, def: MethodDef) -> TokenStream { } fn gen_sys_function(writer: &Writer, namespace: &str, def: MethodDef) -> TokenStream { - let signature = method_def_signature(writer.reader, namespace, def, &[]); - let cfg = signature_cfg(writer.reader, def); + let signature = method_def_signature(namespace, def, &[]); + let cfg = signature_cfg(def); let mut tokens = writer.cfg_features(&cfg); tokens.combine(&gen_link(writer, namespace, &signature, &cfg)); tokens @@ -30,11 +30,11 @@ fn gen_sys_function(writer: &Writer, namespace: &str, def: MethodDef) -> TokenSt fn gen_win_function(writer: &Writer, namespace: &str, def: MethodDef) -> TokenStream { let name = to_ident(def.name()); - let signature = method_def_signature(writer.reader, namespace, def, &[]); + let signature = method_def_signature(namespace, def, &[]); let generics = writer.constraint_generics(&signature.params); let where_clause = writer.where_clause(&signature.params); let abi_return_type = writer.return_sig(&signature); - let cfg = signature_cfg(writer.reader, def); + let cfg = signature_cfg(def); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); let link = gen_link(writer, namespace, &signature, &cfg); diff --git a/crates/libs/bindgen/src/rust/handles.rs b/crates/libs/bindgen/src/rust/handles.rs index b984ca2a4e..a9015ebfe6 100644 --- a/crates/libs/bindgen/src/rust/handles.rs +++ b/crates/libs/bindgen/src/rust/handles.rs @@ -89,7 +89,7 @@ pub fn gen_win_handle(writer: &Writer, def: TypeDef) -> TokenStream { } }; - if let Some(dependency) = type_def_usable_for(writer.reader, def) { + if let Some(dependency) = type_def_usable_for(def) { let type_name = dependency.type_name(); let mut dependency = writer.namespace(type_name.namespace); dependency.push_str(type_name.name); @@ -107,10 +107,10 @@ pub fn gen_win_handle(writer: &Writer, def: TypeDef) -> TokenStream { tokens } -fn type_def_usable_for(reader: &Reader, row: TypeDef) -> Option { +fn type_def_usable_for(row: TypeDef) -> Option { if let Some(attribute) = row.find_attribute("AlsoUsableForAttribute") { if let Some((_, Value::String(name))) = attribute.args().get(0) { - return reader.get_type_def(row.namespace(), name.as_str()).next(); + return row.reader().get_type_def(row.namespace(), name.as_str()).next(); } } None diff --git a/crates/libs/bindgen/src/rust/implements.rs b/crates/libs/bindgen/src/rust/implements.rs index c2b43c2059..d06d8f8f1b 100644 --- a/crates/libs/bindgen/src/rust/implements.rs +++ b/crates/libs/bindgen/src/rust/implements.rs @@ -13,7 +13,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { let constraints = writer.generic_constraints(generics); let generic_names = writer.generic_names(generics); let named_phantoms = writer.generic_named_phantoms(generics); - let cfg = type_def_cfg_impl(writer.reader, def, generics); + let cfg = type_def_cfg_impl(def, generics); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); let mut requires = quote! {}; @@ -46,7 +46,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { if def.flags().contains(TypeAttributes::WindowsRuntime) { // TODO: this awkward wrapping of TypeDefs needs fixing - for interface in type_interfaces(writer.reader, &Type::TypeDef(def, generics.to_vec())) { + for interface in type_interfaces(&Type::TypeDef(def, generics.to_vec())) { if let Type::TypeDef(def, generics) = interface.ty { requires.combine(&gen_required_trait(writer, def, &generics)); } @@ -61,7 +61,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { let method_traits = def.methods().map(|method| { let name = method_names.add(method); - let signature = method_def_signature(writer.reader, def.namespace(), method, generics); + let signature = method_def_signature(def.namespace(), method, generics); let signature_tokens = writer.impl_signature(def, &signature); quote! { fn #name #signature_tokens; } @@ -72,7 +72,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { let method_impls = def.methods().map(|method| { let name = method_names.add(method); - let signature = method_def_signature(writer.reader, def.namespace(), method, generics); + let signature = method_def_signature(def.namespace(), method, generics); let vtbl_signature = writer.vtbl_signature(def, generics, &signature); let invoke_upcall = if def.flags().contains(TypeAttributes::WindowsRuntime) { winrt_methods::gen_upcall(writer, &signature, quote! { this.#name }) } else { com_methods::gen_upcall(writer, &signature, quote! { this.#name }) }; diff --git a/crates/libs/bindgen/src/rust/interfaces.rs b/crates/libs/bindgen/src/rust/interfaces.rs index fa62d58f02..05ef63e016 100644 --- a/crates/libs/bindgen/src/rust/interfaces.rs +++ b/crates/libs/bindgen/src/rust/interfaces.rs @@ -27,10 +27,10 @@ fn gen_win_interface(writer: &Writer, def: TypeDef) -> TokenStream { let is_exclusive = type_def_is_exclusive(def); let phantoms = writer.generic_phantoms(generics); let constraints = writer.generic_constraints(generics); - let cfg = type_def_cfg(writer.reader, def, &[]); + let cfg = type_def_cfg(def, &[]); let doc = writer.cfg_doc(&cfg); let features = writer.cfg_features(&cfg); - let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, generics.to_vec())); + let interfaces = type_interfaces(&Type::TypeDef(def, generics.to_vec())); let vtables = type_def_vtables(def); let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); @@ -110,7 +110,7 @@ fn gen_win_interface(writer: &Writer, def: TypeDef) -> TokenStream { let into = writer.type_name(ty); write!(&mut hierarchy, ", {into}").unwrap(); - hierarchy_cfg = hierarchy_cfg.union(&type_cfg(writer.reader, ty)); + hierarchy_cfg = hierarchy_cfg.union(&type_cfg(ty)); } hierarchy.push_str(");"); @@ -119,7 +119,7 @@ fn gen_win_interface(writer: &Writer, def: TypeDef) -> TokenStream { } else { for ty in &vtables { let into = writer.type_name(ty); - let cfg = writer.cfg_features(&cfg.union(&type_cfg(writer.reader, ty))); + let cfg = writer.cfg_features(&cfg.union(&type_cfg(ty))); tokens.combine("e! { #cfg impl<#constraints> ::windows_core::CanInto<#into> for #ident {} @@ -130,7 +130,7 @@ fn gen_win_interface(writer: &Writer, def: TypeDef) -> TokenStream { if def.flags().contains(TypeAttributes::WindowsRuntime) { for interface in &interfaces { let into = writer.type_name(&interface.ty); - let cfg = writer.cfg_features(&cfg.union(&type_cfg(writer.reader, &interface.ty))); + let cfg = writer.cfg_features(&cfg.union(&type_cfg(&interface.ty))); tokens.combine("e! { #cfg impl<#constraints> ::windows_core::CanTryInto<#into> for #ident {} diff --git a/crates/libs/bindgen/src/rust/iterators.rs b/crates/libs/bindgen/src/rust/iterators.rs index 89f58df5fe..76483129c6 100644 --- a/crates/libs/bindgen/src/rust/iterators.rs +++ b/crates/libs/bindgen/src/rust/iterators.rs @@ -143,7 +143,7 @@ pub fn writer(writer: &Writer, def: TypeDef, generics: &[Type], ident: &TokenStr let wfc = writer.namespace("Windows.Foundation.Collections"); let mut iterable = None; - let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, generics.to_vec())); + let interfaces = type_interfaces(&Type::TypeDef(def, generics.to_vec())); // If the class or interface is not one of the well-known collection interfaces, we then see whether it // implements any one of them. Here is where we favor IVectorView/IVector over IIterable. @@ -153,7 +153,7 @@ pub fn writer(writer: &Writer, def: TypeDef, generics: &[Type], ident: &TokenStr TypeName::IVectorView => { let item = writer.type_name(&interface_generics[0]); let mut cfg = cfg.clone(); - type_def_cfg_combine(writer.reader, *interface, interface_generics, &mut cfg); + type_def_cfg_combine(*interface, interface_generics, &mut cfg); let features = writer.cfg_features(&cfg); return quote! { @@ -180,7 +180,7 @@ pub fn writer(writer: &Writer, def: TypeDef, generics: &[Type], ident: &TokenStr TypeName::IVector => { let item = writer.type_name(&interface_generics[0]); let mut cfg = cfg.clone(); - type_def_cfg_combine(writer.reader, *interface, interface_generics, &mut cfg); + type_def_cfg_combine(*interface, interface_generics, &mut cfg); let features = writer.cfg_features(&cfg); return quote! { @@ -217,7 +217,7 @@ pub fn writer(writer: &Writer, def: TypeDef, generics: &[Type], ident: &TokenStr Some((interface, interface_generics)) => { let item = writer.type_name(&interface_generics[0]); let mut cfg = cfg.clone(); - type_def_cfg_combine(writer.reader, interface, &interface_generics, &mut cfg); + type_def_cfg_combine(interface, &interface_generics, &mut cfg); let features = writer.cfg_features(&cfg); quote! { diff --git a/crates/libs/bindgen/src/rust/mod.rs b/crates/libs/bindgen/src/rust/mod.rs index 4295920e39..fbc3a85c71 100644 --- a/crates/libs/bindgen/src/rust/mod.rs +++ b/crates/libs/bindgen/src/rust/mod.rs @@ -21,8 +21,8 @@ use crate::{Error, Result, Tree}; use cfg::*; use rayon::prelude::*; -pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { - let mut writer = Writer::new(reader, filter, output); +pub fn from_reader(reader: &metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> { + let mut writer = Writer::new(reader, output); writer.package = config.remove("package").is_some(); writer.flatten = config.remove("flatten").is_some(); writer.std = config.remove("std").is_some(); @@ -59,7 +59,7 @@ fn gen_file(writer: &Writer) -> Result<()> { crate::write_to_file(writer.output, try_format(writer, &tokens)) } else { let mut tokens = String::new(); - let root = Tree::new(writer.reader, writer.filter); + let root = Tree::new(writer.reader); for tree in root.nested.values() { tokens.push_str(&namespace(writer, tree)); @@ -71,7 +71,7 @@ fn gen_file(writer: &Writer) -> Result<()> { fn gen_package(writer: &Writer) -> Result<()> { let directory = crate::directory(writer.output); - let root = Tree::new(writer.reader, writer.filter); + let root = Tree::new(writer.reader); let mut root_len = 0; for tree in root.nested.values() { @@ -163,7 +163,7 @@ fn namespace(writer: &Writer, tree: &Tree) -> String { let mut functions = BTreeMap::<&str, TokenStream>::new(); let mut types = BTreeMap::>::new(); - for item in writer.reader.namespace_items(writer.namespace, writer.filter) { + for item in writer.reader.namespace_items(writer.namespace) { match item { Item::Type(def) => { let type_name = def.type_name(); @@ -189,7 +189,7 @@ fn namespace(writer: &Writer, tree: &Tree) -> String { let ident = to_ident(name); let value = writer.guid(&guid); let guid = writer.type_name(&Type::GUID); - let cfg = type_def_cfg(writer.reader, def, &[]); + let cfg = type_def_cfg(def, &[]); let doc = writer.cfg_doc(&cfg); let constant = quote! { #doc @@ -237,7 +237,7 @@ fn namespace_impl(writer: &Writer, tree: &Tree) -> String { writer.namespace = tree.namespace; let mut types = BTreeMap::<&str, TokenStream>::new(); - for item in writer.reader.namespace_items(tree.namespace, writer.filter) { + for item in writer.reader.namespace_items(tree.namespace) { if let Item::Type(def) = item { let type_name = def.type_name(); if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { diff --git a/crates/libs/bindgen/src/rust/standalone.rs b/crates/libs/bindgen/src/rust/standalone.rs index 57583a83a2..7ac9e0a55f 100644 --- a/crates/libs/bindgen/src/rust/standalone.rs +++ b/crates/libs/bindgen/src/rust/standalone.rs @@ -5,8 +5,8 @@ pub fn standalone_imp(writer: &Writer) -> String { let mut functions = BTreeSet::new(); let mut constants = BTreeSet::new(); - for item in writer.reader.items(writer.filter) { - item_collect_standalone(writer.reader, item.clone(), &mut types); + for item in writer.reader.items() { + item_collect_standalone(item.clone(), &mut types); match item { Item::Type(_) => {} @@ -126,19 +126,19 @@ impl SortedTokens { } } -fn item_collect_standalone(reader: &Reader, item: Item, set: &mut BTreeSet) { +fn item_collect_standalone(item: Item, set: &mut BTreeSet) { match item { - Item::Type(def) => type_collect_standalone(reader, &Type::TypeDef(def, vec![]), set), - Item::Const(def) => type_collect_standalone(reader, &def.ty(None).to_const_type(), set), + Item::Type(def) => type_collect_standalone(&Type::TypeDef(def, vec![]), set), + Item::Const(def) => type_collect_standalone(&def.ty(None).to_const_type(), set), Item::Fn(def, namespace) => { - let signature = method_def_signature(reader, namespace, def, &[]); - type_collect_standalone(reader, &signature.return_type, set); - signature.params.iter().for_each(|param| type_collect_standalone(reader, ¶m.ty, set)); + let signature = method_def_signature(namespace, def, &[]); + type_collect_standalone(&signature.return_type, set); + signature.params.iter().for_each(|param| type_collect_standalone(¶m.ty, set)); } } } // TODO: remove or move to riddle -fn type_collect_standalone(reader: &Reader, ty: &Type, set: &mut BTreeSet) { +fn type_collect_standalone(ty: &Type, set: &mut BTreeSet) { let ty = ty.to_underlying_type(); if !set.insert(ty.clone()) { return; @@ -159,15 +159,15 @@ fn type_collect_standalone(reader: &Reader, ty: &Type, set: &mut BTreeSet) // by one architecture but not by another let type_name = def.type_name(); if !type_name.namespace.is_empty() { - for row in reader.get_type_def(type_name.namespace, type_name.name) { + for row in def.reader().get_type_def(type_name.namespace, type_name.name) { if def != row { - type_collect_standalone(reader, &Type::TypeDef(row, Vec::new()), set); + type_collect_standalone(&Type::TypeDef(row, Vec::new()), set); } } } for generic in generics { - type_collect_standalone(reader, generic, set); + type_collect_standalone(generic, set); } for field in def.fields() { let ty = field.ty(Some(def)); @@ -176,30 +176,30 @@ fn type_collect_standalone(reader: &Reader, ty: &Type, set: &mut BTreeSet) continue; } } - type_collect_standalone(reader, &ty, set); + type_collect_standalone(&ty, set); } for method in def.methods() { // Skip delegate pseudo-constructors. if method.name() == ".ctor" { continue; } - let signature = method_def_signature(reader, def.namespace(), method, generics); - type_collect_standalone(reader, &signature.return_type, set); - signature.params.iter().for_each(|param| type_collect_standalone(reader, ¶m.ty, set)); + let signature = method_def_signature(def.namespace(), method, generics); + type_collect_standalone(&signature.return_type, set); + signature.params.iter().for_each(|param| type_collect_standalone(¶m.ty, set)); } - for interface in type_interfaces(reader, &ty) { - type_collect_standalone(reader, &interface.ty, set); + for interface in type_interfaces(&ty) { + type_collect_standalone(&interface.ty, set); } if def.kind() == TypeKind::Struct && def.fields().next().is_none() && type_def_guid(def).is_some() { set.insert(Type::GUID); } - type_collect_standalone_nested(reader, def, set); + type_collect_standalone_nested(def, set); } -fn type_collect_standalone_nested(reader: &Reader, td: TypeDef, set: &mut BTreeSet) { - for nested in reader.nested_types(td) { - type_collect_standalone_nested(reader, nested, set); +fn type_collect_standalone_nested(td: TypeDef, set: &mut BTreeSet) { + for nested in td.reader().nested_types(td) { + type_collect_standalone_nested(nested, set); for field in nested.fields() { let ty = field.ty(Some(nested)); @@ -210,7 +210,7 @@ fn type_collect_standalone_nested(reader: &Reader, td: TypeDef, set: &mut BTreeS continue; } - type_collect_standalone(reader, &ty, set); + type_collect_standalone(&ty, set); } } } diff --git a/crates/libs/bindgen/src/rust/structs.rs b/crates/libs/bindgen/src/rust/structs.rs index 13047d2197..dda7fc21b0 100644 --- a/crates/libs/bindgen/src/rust/structs.rs +++ b/crates/libs/bindgen/src/rust/structs.rs @@ -37,7 +37,7 @@ fn gen_struct_with_name(writer: &Writer, def: TypeDef, struct_name: &str, cfg: & } let flags = def.flags(); - let cfg = cfg.union(&type_def_cfg(writer.reader, def, &[])); + let cfg = cfg.union(&type_def_cfg(def, &[])); let repr = if let Some(layout) = def.class_layout() { let packing = Literal::usize_unsuffixed(layout.packing_size()); @@ -52,10 +52,10 @@ fn gen_struct_with_name(writer: &Writer, def: TypeDef, struct_name: &str, cfg: & if f.flags().contains(FieldAttributes::Literal) { quote! {} - } else if !writer.sys && flags.contains(TypeAttributes::ExplicitLayout) && !field_is_copyable(writer.reader, f, def) { + } else if !writer.sys && flags.contains(TypeAttributes::ExplicitLayout) && !field_is_copyable(f, def) { let ty = writer.type_default_name(&ty); quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } - } else if !writer.sys && !flags.contains(TypeAttributes::WindowsRuntime) && !field_is_blittable(writer.reader, f, def) { + } else if !writer.sys && !flags.contains(TypeAttributes::WindowsRuntime) && !field_is_blittable(f, def) { if let Type::Win32Array(ty, len) = ty { let ty = writer.type_default_name(&ty); quote! { pub #name: [::std::mem::ManuallyDrop<#ty>; #len], } @@ -115,7 +115,7 @@ fn gen_windows_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &C quote! {} } else { let features = writer.cfg_features(cfg); - let is_copy = type_def_is_blittable(writer.reader, def); + let is_copy = type_def_is_blittable(def); let type_kind = if is_copy { quote! { CopyType } @@ -131,7 +131,7 @@ fn gen_windows_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &C }; if def.flags().contains(TypeAttributes::WindowsRuntime) { - let signature = Literal::byte_string(type_def_signature(writer.reader, def, &[]).as_bytes()); + let signature = Literal::byte_string(type_def_signature(def, &[]).as_bytes()); tokens.combine("e! { #features @@ -148,7 +148,7 @@ fn gen_windows_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &C fn gen_compare_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { let features = writer.cfg_features(cfg); - if writer.sys || type_def_has_explicit_layout(writer.reader, def) || type_def_has_packing(writer.reader, def) || type_def_has_callback(writer.reader, def) { + if writer.sys || type_def_has_explicit_layout(def) || type_def_has_packing(def) || type_def_has_callback(def) { quote! {} } else { let fields = def.fields().filter_map(|f| { @@ -174,7 +174,7 @@ fn gen_compare_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &C } fn gen_debug(writer: &Writer, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> TokenStream { - if writer.sys || type_def_has_explicit_layout(writer.reader, def) || type_def_has_packing(writer.reader, def) { + if writer.sys || type_def_has_explicit_layout(def) || type_def_has_packing(def) { quote! {} } else { let name = ident.as_str(); @@ -187,7 +187,7 @@ fn gen_debug(writer: &Writer, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> T let name = f.name(); let ident = to_ident(name); let ty = f.ty(Some(def)); - if type_has_callback(writer.reader, &ty) { + if type_has_callback(&ty) { None } else { Some(quote! { .field(#name, &self.#ident) }) @@ -209,7 +209,7 @@ fn gen_debug(writer: &Writer, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> T fn gen_copy_clone(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { let features = writer.cfg_features(cfg); - if writer.sys || type_def_is_copyable(writer.reader, def) { + if writer.sys || type_def_is_copyable(def) { quote! { #features impl ::core::marker::Copy for #name {} @@ -237,7 +237,7 @@ fn gen_copy_clone(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) let name = to_ident(f.name()); if f.flags().contains(FieldAttributes::Literal) { quote! {} - } else if field_is_blittable(writer.reader, f, def) { + } else if field_is_blittable(f, def) { quote! { #name: self.#name } } else { quote! { #name: self.#name.clone() } diff --git a/crates/libs/bindgen/src/rust/winrt_methods.rs b/crates/libs/bindgen/src/rust/winrt_methods.rs index 1aac3038a5..bea838c1f8 100644 --- a/crates/libs/bindgen/src/rust/winrt_methods.rs +++ b/crates/libs/bindgen/src/rust/winrt_methods.rs @@ -2,15 +2,15 @@ use super::*; // TODO take Signature instead of MethodDef (wherever MethodDef is found) pub fn writer(writer: &Writer, def: TypeDef, generic_types: &[Type], kind: InterfaceKind, method: MethodDef, method_names: &mut MethodNames, virtual_names: &mut MethodNames) -> TokenStream { - let signature = method_def_signature(writer.reader, def.namespace(), method, generic_types); + let signature = method_def_signature(def.namespace(), method, generic_types); let params = &signature.params; let name = method_names.add(method); let interface_name = writer.type_def_name(def, generic_types); let vname = virtual_names.add(method); let generics = writer.constraint_generics(params); let where_clause = writer.where_clause(params); - let mut cfg = signature_cfg(writer.reader, method); - type_def_cfg_combine(writer.reader, def, generic_types, &mut cfg); + let mut cfg = signature_cfg(method); + type_def_cfg_combine(def, generic_types, &mut cfg); let doc = writer.cfg_method_doc(&cfg); let features = writer.cfg_features(&cfg); let args = gen_winrt_abi_args(writer, params); @@ -109,11 +109,11 @@ fn gen_winrt_params(writer: &Writer, params: &[SignatureParam]) -> TokenStream { if param.def.flags().contains(ParamAttributes::In) { if param.ty.is_winrt_array() { result.combine("e! { #name: &[#default_type], }); - } else if signature_param_is_convertible(writer.reader, param) { + } else if signature_param_is_convertible(param) { let (position, _) = generic_params.next().unwrap(); let kind: TokenStream = format!("P{position}").into(); result.combine("e! { #name: #kind, }); - } else if type_is_blittable(writer.reader, ¶m.ty) { + } else if type_is_blittable(¶m.ty) { result.combine("e! { #name: #kind, }); } else { result.combine("e! { #name: &#kind, }); @@ -137,16 +137,16 @@ fn gen_winrt_abi_args(writer: &Writer, params: &[SignatureParam]) -> TokenStream let param = if param.def.flags().contains(ParamAttributes::In) { if param.ty.is_winrt_array() { - if type_is_blittable(writer.reader, ¶m.ty) { + if type_is_blittable(¶m.ty) { quote! { #name.len() as u32, #name.as_ptr(), } } else { quote! { #name.len() as u32, ::core::mem::transmute(#name.as_ptr()), } } } else if type_is_non_exclusive_winrt_interface(¶m.ty) { quote! { #name.try_into_param()?.abi(), } - } else if type_is_borrowed(writer.reader, ¶m.ty) { + } else if type_is_borrowed(¶m.ty) { quote! { #name.into_param().abi(), } - } else if type_is_blittable(writer.reader, ¶m.ty) { + } else if type_is_blittable(¶m.ty) { if param.ty.is_const_ref() { quote! { &#name, } } else { @@ -156,14 +156,14 @@ fn gen_winrt_abi_args(writer: &Writer, params: &[SignatureParam]) -> TokenStream quote! { ::core::mem::transmute_copy(#name), } } } else if param.ty.is_winrt_array() { - if type_is_blittable(writer.reader, ¶m.ty) { + if type_is_blittable(¶m.ty) { quote! { #name.len() as u32, #name.as_mut_ptr(), } } else { quote! { #name.len() as u32, ::core::mem::transmute_copy(&#name), } } } else if param.ty.is_winrt_array_ref() { quote! { #name.set_abi_len(), #name as *mut _ as _, } - } else if type_is_blittable(writer.reader, ¶m.ty) { + } else if type_is_blittable(¶m.ty) { quote! { #name, } } else { quote! { #name as *mut _ as _, } @@ -195,7 +195,7 @@ pub fn gen_upcall(writer: &Writer, sig: &Signature, inner: TokenStream) -> Token } } _ => { - let forget = if type_is_blittable(writer.reader, &sig.return_type) { + let forget = if type_is_blittable(&sig.return_type) { quote! {} } else { quote! { ::core::mem::forget(ok__); } diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index 332a8d63bf..5145817ceb 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -3,7 +3,6 @@ use super::*; #[derive(Clone)] pub struct Writer<'a> { pub reader: &'a Reader, - pub filter: &'a metadata::Filter<'a>, pub output: &'a str, pub namespace: &'a str, pub implement: bool, // TODO: ideally we can use this to generate implementation traits on the fly and @@ -22,10 +21,9 @@ pub struct Writer<'a> { } impl<'a> Writer<'a> { - pub fn new(reader: &'a Reader, filter: &'a metadata::Filter, output: &'a str) -> Self { + pub fn new(reader: &'a Reader, output: &'a str) -> Self { Self { reader, - filter, output, namespace: "", implement: false, @@ -212,7 +210,7 @@ impl<'a> Writer<'a> { TypeKind::Enum => self.type_def_name(*def, &[]), TypeKind::Struct => { let tokens = self.type_def_name(*def, &[]); - if type_def_is_blittable(self.reader, *def) { + if type_def_is_blittable(*def) { tokens } else { quote! { ::std::mem::MaybeUninit<#tokens> } @@ -283,7 +281,7 @@ impl<'a> Writer<'a> { } /// The signature params which are generic (along with their relative index) pub fn generic_params<'b>(&'b self, params: &'b [SignatureParam]) -> impl Iterator + 'b { - params.iter().filter(move |param| signature_param_is_convertible(self.reader, param)).enumerate() + params.iter().filter(move |param| signature_param_is_convertible(param)).enumerate() } /// The generic param names (i.e., `T` in `fn foo()`) pub fn constraint_generics(&self, params: &[SignatureParam]) -> TokenStream { @@ -641,7 +639,7 @@ impl<'a> Writer<'a> { pub fn interface_winrt_trait(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream { 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()); + let type_signature = Literal::byte_string(type_def_signature(def, generics).as_bytes()); quote! { ::windows_core::imp::ConstBuffer::from_slice(#type_signature) } } else { let signature = Literal::byte_string( @@ -782,8 +780,8 @@ impl<'a> Writer<'a> { continue; } 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 = method_def_signature(def.namespace(), method, generics); + let mut cfg = signature_cfg(method); let signature = self.vtbl_signature(def, generics, &signature); cfg.add_feature(def.namespace()); let cfg_all = self.cfg_features(&cfg); diff --git a/crates/libs/bindgen/src/tree.rs b/crates/libs/bindgen/src/tree.rs index 474d2a2719..9fda6a302a 100644 --- a/crates/libs/bindgen/src/tree.rs +++ b/crates/libs/bindgen/src/tree.rs @@ -7,10 +7,10 @@ pub struct Tree<'a> { } impl<'a> Tree<'a> { - pub fn new(reader: &'a metadata::Reader, filter: &'a metadata::Filter) -> Self { + pub fn new(reader: &'a metadata::Reader) -> Self { let mut tree = Tree::from_namespace(""); for ns in reader.namespaces() { - if filter.includes_namespace(ns) { + if reader.includes_namespace(ns) { tree.insert_namespace(ns, 0); } } diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs index b315da514f..51bc55b140 100644 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ b/crates/libs/bindgen/src/winmd/from_reader.rs @@ -1,7 +1,7 @@ use super::*; use crate::winmd::{self, writer}; -pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, config: std::collections::BTreeMap<&str, &str>, output: &str) -> crate::Result<()> { +pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap<&str, &str>, output: &str) -> crate::Result<()> { let mut writer = winmd::Writer::new(output); // TODO: do we need any configuration values for winmd generation? @@ -15,7 +15,7 @@ pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, config: // TODO: just use the reader directly since we now have everything in the reader, there's no need to abstract // away the source format. Few reprs is always better. - for item in reader.items(filter) { + for item in reader.items() { // TODO: cover all variants let metadata::Item::Type(def) = item else { continue; diff --git a/crates/libs/bindgen/src/winmd/verify.rs b/crates/libs/bindgen/src/winmd/verify.rs index 5a856445f3..6b36213fc3 100644 --- a/crates/libs/bindgen/src/winmd/verify.rs +++ b/crates/libs/bindgen/src/winmd/verify.rs @@ -1,7 +1,7 @@ use super::*; -pub fn verify(reader: &metadata::Reader, filter: &metadata::Filter) -> crate::Result<()> { - let unused: Vec<&str> = filter.unused(reader).collect(); +pub fn verify(reader: &metadata::Reader) -> crate::Result<()> { + let unused: Vec<&str> = reader.unused().collect(); if !unused.is_empty() { let mut message = "unused filters".to_string(); @@ -13,7 +13,7 @@ pub fn verify(reader: &metadata::Reader, filter: &metadata::Filter) -> crate::Re return Err(crate::Error::new(&message)); } - for item in reader.items(filter) { + for item in reader.items() { // TODO: cover all variants let metadata::Item::Type(def) = item else { continue; diff --git a/crates/libs/metadata/src/filter.rs b/crates/libs/metadata/src/filter.rs index c7a6ceaf75..057586a6c9 100644 --- a/crates/libs/metadata/src/filter.rs +++ b/crates/libs/metadata/src/filter.rs @@ -1,18 +1,16 @@ -use super::*; - #[derive(Default)] -pub struct Filter<'a>(Vec<(&'a str, bool)>); +pub struct Filter(pub Vec<(String, bool)>); -impl<'a> Filter<'a> { - pub fn new(include: &[&'a str], exclude: &[&'a str]) -> Self { +impl Filter { + pub fn new(include: &[&str], exclude: &[&str]) -> Self { let mut rules = vec![]; for include in include { - rules.push((*include, true)); + rules.push((include.to_string(), true)); } for exclude in exclude { - rules.push((*exclude, false)); + rules.push((exclude.to_string(), false)); } rules.sort_unstable_by(|left, right| { @@ -25,7 +23,7 @@ impl<'a> Filter<'a> { } pub fn includes_namespace(&self, namespace: &str) -> bool { - if self.is_empty() { + if self.0.is_empty() { return true; } @@ -35,12 +33,12 @@ impl<'a> Filter<'a> { if rule.0.starts_with(namespace) { return true; } - if namespace.starts_with(rule.0) { + if namespace.starts_with(&rule.0) { return true; } } else { // exclude - if namespace.starts_with(rule.0) { + if namespace.starts_with(&rule.0) { return false; } } @@ -50,30 +48,18 @@ impl<'a> Filter<'a> { } pub fn includes_type_name(&self, namespace: &str, name: &str) -> bool { - if self.is_empty() { + if self.0.is_empty() { return true; } for rule in &self.0 { - if match_type_name(rule.0, namespace, name) { + if match_type_name(&rule.0, namespace, name) { return rule.1; } } false } - - pub fn includes(&self) -> impl Iterator + '_ { - self.0.iter().filter_map(|(name, include)| if *include { Some(*name) } else { None }) - } - - fn is_empty(&self) -> bool { - self.0.is_empty() - } - - pub fn unused(&self, reader: &'a Reader) -> impl Iterator + '_ { - self.0.iter().filter_map(|(name, _)| if reader.unused(name) { Some(*name) } else { None }) - } } fn match_type_name(rule: &str, namespace: &str, name: &str) -> bool { @@ -97,7 +83,7 @@ mod tests { use super::*; fn includes_type_name(filter: &Filter, full_name: &'static str) -> bool { - let type_name = parse_type_name(full_name); + let type_name = crate::parse_type_name(full_name); filter.includes_type_name(type_name.0, type_name.1) } @@ -121,8 +107,6 @@ mod tests { let exclude = ["N2", "N3.N4"]; let f = Filter::new(&include, &exclude); - assert!(!f.is_empty()); - assert!(!includes_type_name(&f, "NN.T")); assert!(includes_type_name(&f, "N1.T")); @@ -140,8 +124,6 @@ mod tests { let exclude = ["N.N3", "N.N4"]; let f = Filter::new(&include, &exclude); - assert!(!f.is_empty()); - assert!(includes_type_name(&f, "N.N1.T")); assert!(includes_type_name(&f, "N.N2.T")); @@ -155,8 +137,6 @@ mod tests { let exclude = ["N.T"]; let f = Filter::new(&include, &exclude); - assert!(!f.is_empty()); - assert!(!includes_type_name(&f, "N.T")); } } diff --git a/crates/libs/metadata/src/lib.rs b/crates/libs/metadata/src/lib.rs index 19fba03e68..4606ca7ff4 100644 --- a/crates/libs/metadata/src/lib.rs +++ b/crates/libs/metadata/src/lib.rs @@ -21,11 +21,11 @@ pub use blob::*; pub use codes::*; pub use column::*; pub use file::*; -pub use filter::*; +use filter::*; pub use r#type::*; pub use reader::*; pub use row::*; -pub use table::*; +use table::*; pub use tables::*; pub use type_name::*; diff --git a/crates/libs/metadata/src/reader.rs b/crates/libs/metadata/src/reader.rs index fefe6eee37..51b4056d98 100644 --- a/crates/libs/metadata/src/reader.rs +++ b/crates/libs/metadata/src/reader.rs @@ -15,11 +15,17 @@ pub struct Reader { // TODO: riddle should just avoid nested structs nested: HashMap>, + + filter: Filter, } impl Reader { pub fn new(files: Vec) -> &'static Self { - let reader: &'static mut Reader = Box::leak(Box::new(Self { items: Default::default(), nested: Default::default() })); + Self::filter(files, &[], &[]) + } + + pub fn filter(files: Vec, include: &[&str], exclude: &[&str]) -> &'static Self { + let reader: &'static mut Reader = Box::leak(Box::new(Self { items: Default::default(), nested: Default::default(), filter: Filter::new(include, exclude) })); for mut file in files { file.reader = reader as *mut Reader; @@ -64,19 +70,27 @@ impl Reader { reader } + pub fn includes_namespace(&self, namespace: &str) -> bool { + self.filter.includes_namespace(namespace) + } + pub fn namespaces(&self) -> impl Iterator + '_ { self.items.keys().copied() } - pub fn items<'a>(&'a self, filter: &'a Filter) -> impl Iterator + '_ { - self.items.iter().filter(move |(namespace, _)| filter.includes_namespace(namespace)).flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned() + pub fn items(&self) -> impl Iterator + '_ { + self.items.iter().filter(move |(namespace, _)| self.filter.includes_namespace(namespace)).flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| self.filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned() + } + + pub fn namespace_items(&self, namespace: &str) -> impl Iterator + '_ { + self.items.get_key_value(namespace).into_iter().flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| self.filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned() } - pub fn namespace_items<'a>(&'a self, namespace: &str, filter: &'a Filter) -> impl Iterator + '_ { - self.items.get_key_value(namespace).into_iter().flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned() + pub fn unused(&self) -> impl Iterator + '_ { + self.filter.0.iter().filter_map(|(name, _)| if self.is_unused(name) { Some(name.as_str()) } else { None }) } - pub fn unused(&self, filter: &str) -> bool { + fn is_unused(&self, filter: &str) -> bool { // Match namespaces if self.items.contains_key(filter) { return false; diff --git a/crates/tests/metadata/tests/attribute_enum.rs b/crates/tests/metadata/tests/attribute_enum.rs index 6393b8cf67..6944bbf45e 100644 --- a/crates/tests/metadata/tests/attribute_enum.rs +++ b/crates/tests/metadata/tests/attribute_enum.rs @@ -3,7 +3,7 @@ use metadata::*; #[test] fn attribute_enum() { let files = tool_lib::default_metadata(); - let reader = &Reader::new(files); + let reader = Reader::new(files); let (method, _) = reader .get_method_def("Windows.Win32.UI.WindowsAndMessaging", "SetWindowLongPtrA") diff --git a/crates/tests/metadata/tests/fn_call_size.rs b/crates/tests/metadata/tests/fn_call_size.rs index 767270bc54..4e1c7182b1 100644 --- a/crates/tests/metadata/tests/fn_call_size.rs +++ b/crates/tests/metadata/tests/fn_call_size.rs @@ -6,7 +6,7 @@ fn size() { // dumpbin /exports kernel32.lib | findstr /i RtmConvertIpv6AddressAndLengthToNetAddress let files = tool_lib::default_metadata(); - let reader = &Reader::new(files); + let reader = Reader::new(files); assert_eq!( struct_size(reader, "Windows.Win32.System.Variant", "VARIANT"), diff --git a/crates/tests/metadata/tests/unused.rs b/crates/tests/metadata/tests/unused.rs index 25b4ec7693..ee6ae69be9 100644 --- a/crates/tests/metadata/tests/unused.rs +++ b/crates/tests/metadata/tests/unused.rs @@ -3,12 +3,12 @@ use metadata::*; #[test] fn test() { let files = tool_lib::default_metadata(); - let reader = &Reader::new(files); - let filter = Filter::new( + let reader = Reader::filter( + files, &["Windows", "BadNamespace", "Windows.AI"], &["Windows.Foundation.Rect", "Windows.Foundation.BadType"], ); - let unused: Vec<&str> = filter.unused(reader).collect(); + let unused: Vec<&str> = reader.unused().collect(); assert_eq!(unused, ["Windows.Foundation.BadType", "BadNamespace"]); } diff --git a/crates/tests/riddle/tests/composition.rs b/crates/tests/riddle/tests/composition.rs index 6dbfbcb19a..61a2566342 100644 --- a/crates/tests/riddle/tests/composition.rs +++ b/crates/tests/riddle/tests/composition.rs @@ -7,6 +7,5 @@ // #[test] // fn test() { // let files = run_riddle("composition", "winrt", &[]); -// let _reader = &Reader::new(&files); - +// let reader = Reader::new(files); // } diff --git a/crates/tests/riddle/tests/generic_interfaces.rs b/crates/tests/riddle/tests/generic_interfaces.rs index cb305a13c5..94e09db151 100644 --- a/crates/tests/riddle/tests/generic_interfaces.rs +++ b/crates/tests/riddle/tests/generic_interfaces.rs @@ -6,9 +6,7 @@ fn test() { let files = run_riddle("generic_interfaces", "winrt", &[]); let reader = Reader::new(files); - let types: Vec = reader - .namespace_items("Test", &Default::default()) - .collect(); + let types: Vec = reader.namespace_items("Test").collect(); assert_eq!(types.len(), 4); diff --git a/crates/tests/riddle/tests/nested_module.rs b/crates/tests/riddle/tests/nested_module.rs index f8e8f4972a..c95402862b 100644 --- a/crates/tests/riddle/tests/nested_module.rs +++ b/crates/tests/riddle/tests/nested_module.rs @@ -6,9 +6,7 @@ fn test() { let files = run_riddle("nested_module", "winrt", &[]); let reader = Reader::new(files); - let types: Vec = reader - .namespace_items("Test", &Default::default()) - .collect(); + let types: Vec = reader.namespace_items("Test").collect(); assert_eq!(types.len(), 1); let Item::Type(def) = types[0] else { @@ -22,9 +20,7 @@ fn test() { assert_eq!(fields[0].name(), "field"); assert!(matches!(fields[0].ty(None), Type::I32)); - let types: Vec = reader - .namespace_items("Test.NestedModule", &Default::default()) - .collect(); + let types: Vec = reader.namespace_items("Test.NestedModule").collect(); assert_eq!(types.len(), 1); let Item::Type(def) = types[0] else { diff --git a/crates/tools/lib/src/lib.rs b/crates/tools/lib/src/lib.rs index f81fc54f4b..8a4de76d75 100644 --- a/crates/tools/lib/src/lib.rs +++ b/crates/tools/lib/src/lib.rs @@ -27,7 +27,7 @@ pub fn libraries() -> BTreeMap> { let mut libraries = BTreeMap::>::new(); let files = default_metadata(); - let reader = &metadata::Reader::new(files); + let reader = metadata::Reader::new(files); combine_libraries(reader, &mut libraries); // StgConvertPropertyToVariant was removed https://github.com/microsoft/win32metadata/issues/1566 @@ -41,7 +41,7 @@ pub fn libraries() -> BTreeMap> { .expect("invalid winmd"), ]; - let reader = &metadata::Reader::new(compat); + let reader = metadata::Reader::new(compat); combine_libraries(reader, &mut libraries); libraries @@ -51,7 +51,7 @@ fn combine_libraries( reader: &metadata::Reader, libraries: &mut BTreeMap>, ) { - for item in reader.items(&Default::default()) { + for item in reader.items() { let metadata::Item::Fn(method, _) = item else { continue; };