Skip to content

Commit

Permalink
Simplify metadata reader (#2682)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Oct 17, 2023
1 parent 41ad38d commit 4c234b5
Show file tree
Hide file tree
Showing 58 changed files with 1,878 additions and 1,983 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/fmt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Update toolchain
run: rustup update --no-self-update stable && rustup default stable
- name: Check
run: cargo fmt --all -- --check
2 changes: 2 additions & 0 deletions .github/workflows/gen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Update toolchain
run: rustup update --no-self-update stable && rustup default stable
- name: Run
run: cargo run -p tool_${{ matrix.tool }}
- name: Check
Expand Down
10 changes: 5 additions & 5 deletions crates/libs/bindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,15 @@ where
let output = canonicalize(output)?;

let input = read_input(&input)?;
let reader = metadata::Reader::new(&input);
let reader = metadata::Reader::new(input);
let filter = metadata::Filter::new(&include, &exclude);

winmd::verify(&reader, &filter)?;
winmd::verify(reader, &filter)?;

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, &filter, config, &output)?,
"winmd" => winmd::from_reader(reader, &filter, config, &output)?,
"rs" => rust::from_reader(reader, &filter, config, &output)?,
_ => return Err(Error::new("output extension must be one of winmd/rdl/rs")),
}

Expand Down
323 changes: 179 additions & 144 deletions crates/libs/bindgen/src/metadata.rs

Large diffs are not rendered by default.

56 changes: 28 additions & 28 deletions crates/libs/bindgen/src/rdl/from_reader.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;
use crate::tokens::{quote, to_ident, TokenStream};
use crate::{rdl, Error, Result, Tree};
use metadata::RowReader;
use metadata::*;

pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
let dialect = match config.remove("type") {
Expand Down Expand Up @@ -58,7 +58,7 @@ enum Dialect {
}

struct Writer<'a> {
reader: &'a metadata::Reader<'a>,
reader: &'a metadata::Reader,
filter: &'a metadata::Filter<'a>,
namespace: &'a str,
dialect: Dialect,
Expand Down Expand Up @@ -137,7 +137,7 @@ impl<'a> Writer<'a> {
if !tree.namespace.is_empty() {
for item in self.reader.namespace_items(tree.namespace, self.filter).filter(|item| match item {
metadata::Item::Type(def) => {
let winrt = self.reader.type_def_flags(*def).contains(metadata::TypeAttributes::WindowsRuntime);
let winrt = def.flags().contains(metadata::TypeAttributes::WindowsRuntime);
match self.dialect {
Dialect::Win32 => !winrt,
Dialect::WinRT => winrt,
Expand All @@ -148,7 +148,7 @@ impl<'a> Writer<'a> {
match item {
metadata::Item::Type(def) => types.push(self.type_def(def)),
metadata::Item::Const(field) => constants.push(self.constant(field)),
metadata::Item::Fn(method, namespace) => functions.push(self.function(method, &namespace)),
metadata::Item::Fn(method, namespace) => functions.push(self.function(method, namespace)),
}
}
}
Expand All @@ -161,17 +161,17 @@ impl<'a> Writer<'a> {
}

fn function(&self, def: metadata::MethodDef, _namespace: &str) -> TokenStream {
let name = to_ident(self.reader.method_def_name(def));
let name = to_ident(def.name());
quote! { fn #name(); }
}

fn constant(&self, def: metadata::Field) -> TokenStream {
let name = to_ident(self.reader.field_name(def));
let name = to_ident(def.name());
quote! { const #name: i32 = 0; }
}

fn type_def(&self, def: metadata::TypeDef) -> TokenStream {
if let Some(extends) = self.reader.type_def_extends(def) {
if let Some(extends) = def.extends() {
if extends.namespace == "System" {
if extends.name == "Enum" {
self.enum_def(def)
Expand All @@ -191,7 +191,7 @@ impl<'a> Writer<'a> {
}

fn enum_def(&self, def: metadata::TypeDef) -> TokenStream {
let name = to_ident(self.reader.type_def_name(def));
let name = to_ident(def.name());

quote! {
struct #name {
Expand All @@ -201,11 +201,11 @@ impl<'a> Writer<'a> {
}

fn struct_def(&self, def: metadata::TypeDef) -> TokenStream {
let name = to_ident(self.reader.type_def_name(def));
let name = to_ident(def.name());

let fields = self.reader.type_def_fields(def).map(|field| {
let name = to_ident(self.reader.field_name(field));
let ty = self.ty(&self.reader.field_type(field, Some(def)));
let fields = def.fields().map(|field| {
let name = to_ident(field.name());
let ty = self.ty(&field.ty(Some(def)));
quote! {
#name: #ty
}
Expand All @@ -219,7 +219,7 @@ impl<'a> Writer<'a> {
}

fn delegate_def(&self, def: metadata::TypeDef) -> TokenStream {
let name = to_ident(self.reader.type_def_name(def));
let name = to_ident(def.name());

quote! {
struct #name {
Expand All @@ -229,7 +229,7 @@ impl<'a> Writer<'a> {
}

fn class_def(&self, def: metadata::TypeDef) -> TokenStream {
let name = to_ident(self.reader.type_def_name(def));
let name = to_ident(def.name());
let implements = self.implements(def, &[]);

quote! {
Expand All @@ -238,20 +238,20 @@ impl<'a> Writer<'a> {
}

fn interface_def(&self, def: metadata::TypeDef) -> TokenStream {
let name = to_ident(self.reader.type_def_name(def));
let generics = &metadata::type_def_generics(self.reader, def);
let name = to_ident(def.name());
let generics = &metadata::type_def_generics(def);
let implements = self.implements(def, generics);

let methods = self.reader.type_def_methods(def).map(|method| {
let name = to_ident(self.reader.method_def_name(method));
let methods = def.methods().map(|method| {
let name = to_ident(method.name());

// TODO: use reader.method_def_signature instead
let signature = metadata::method_def_signature(self.reader, self.reader.type_def_namespace(def), method, generics);
let signature = metadata::method_def_signature(self.reader, def.namespace(), method, generics);

let return_type = self.return_type(&signature.return_type);

let params = signature.params.iter().map(|param| {
let name = to_ident(self.reader.param_name(param.def));
let name = to_ident(param.def.name());
let ty = self.ty(&param.ty);
quote! { #name: #ty }
});
Expand Down Expand Up @@ -287,16 +287,16 @@ impl<'a> Writer<'a> {
// TODO: then list default interface first
// Then everything else

for imp in self.reader.type_def_interface_impls(def) {
let ty = self.reader.interface_impl_type(imp, generics);
if self.reader.has_attribute(imp, "DefaultAttribute") {
for imp in def.interface_impls() {
let ty = imp.ty(generics);
if imp.has_attribute("DefaultAttribute") {
types.insert(0, self.ty(&ty));
} else {
types.push(self.ty(&ty));
}
}

if let Some(type_name) = self.reader.type_def_extends(def) {
if let Some(type_name) = def.extends() {
if type_name != metadata::TypeName::Object {
let namespace = self.namespace(type_name.namespace);
let name = to_ident(type_name.name);
Expand Down Expand Up @@ -349,8 +349,8 @@ impl<'a> Writer<'a> {
metadata::Type::IUnknown => quote! { IUnknown },

metadata::Type::TypeDef(def, generics) => {
let namespace = self.namespace(self.reader.type_def_namespace(*def));
let name = to_ident(self.reader.type_def_name(*def));
let namespace = self.namespace(def.namespace());
let name = to_ident(def.name());
if generics.is_empty() {
quote! { #namespace #name }
} else {
Expand All @@ -360,13 +360,13 @@ impl<'a> Writer<'a> {
}

metadata::Type::TypeRef(code) => {
let type_name = self.reader.type_def_or_ref(*code);
let type_name = code.type_name();
let namespace = self.namespace(type_name.namespace);
let name = to_ident(type_name.name);
quote! { #namespace #name }
}

metadata::Type::GenericParam(generic) => self.reader.generic_param_name(*generic).into(),
metadata::Type::GenericParam(generic) => generic.name().into(),
metadata::Type::WinrtArray(ty) => self.ty(ty),
metadata::Type::WinrtArrayRef(ty) => self.ty(ty),
metadata::Type::ConstRef(ty) => self.ty(ty),
Expand Down
50 changes: 25 additions & 25 deletions crates/libs/bindgen/src/rust/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ impl<'a> Cfg<'a> {
}
}

pub fn field_cfg<'a>(reader: &'a Reader<'a>, row: Field) -> Cfg<'a> {
pub fn field_cfg(reader: &Reader, row: Field) -> Cfg {
let mut cfg = Cfg::default();
field_cfg_combine(reader, row, None, &mut cfg);
cfg
}
fn field_cfg_combine<'a>(reader: &'a Reader, row: Field, enclosing: Option<TypeDef>, cfg: &mut Cfg<'a>) {
type_cfg_combine(reader, &reader.field_type(row, enclosing), cfg)
type_cfg_combine(reader, &row.ty(enclosing), cfg)
}

pub fn type_def_cfg<'a>(reader: &'a Reader, row: TypeDef, generics: &[Type]) -> Cfg<'a> {
let mut cfg = Cfg::default();
type_def_cfg_combine(reader, row, generics, &mut cfg);
cfg_add_attributes(reader, &mut cfg, row);
cfg_add_attributes(&mut cfg, row);
cfg
}
pub fn type_def_cfg_impl<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type]) -> Cfg<'a> {
Expand All @@ -51,85 +51,85 @@ pub fn type_def_cfg_impl<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type]
fn combine<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) {
type_def_cfg_combine(reader, def, generics, cfg);

for method in reader.type_def_methods(def) {
signature_cfg_combine(reader, &reader.method_def_signature(method, generics), cfg);
for method in def.methods() {
signature_cfg_combine(reader, &method.signature(generics), cfg);
}
}

combine(reader, def, generics, &mut cfg);

for def in type_def_vtables(reader, def) {
for def in type_def_vtables(def) {
if let Type::TypeDef(def, generics) = def {
combine(reader, def, &generics, &mut cfg);
}
}

if reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) {
for interface in type_def_interfaces(reader, def, generics) {
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);
}
}
}

cfg_add_attributes(reader, &mut cfg, def);
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>) {
let type_name = reader.type_def_type_name(row);
let type_name = row.type_name();

for generic in generics {
type_cfg_combine(reader, generic, cfg);
}

if cfg.types.entry(type_name.namespace).or_default().insert(row) {
match reader.type_def_kind(row) {
match row.kind() {
TypeKind::Class => {
if let Some(default_interface) = type_def_default_interface(reader, row) {
if let Some(default_interface) = type_def_default_interface(row) {
type_cfg_combine(reader, &default_interface, cfg);
}
}
TypeKind::Interface => {
if !reader.type_def_flags(row).contains(TypeAttributes::WindowsRuntime) {
for def in type_def_vtables(reader, row) {
if !row.flags().contains(TypeAttributes::WindowsRuntime) {
for def in type_def_vtables(row) {
if let Type::TypeDef(def, _) = def {
cfg.add_feature(reader.type_def_namespace(def));
cfg.add_feature(def.namespace());
}
}
}
}
TypeKind::Struct => {
reader.type_def_fields(row).for_each(|field| field_cfg_combine(reader, field, Some(row), cfg));
row.fields().for_each(|field| field_cfg_combine(reader, field, Some(row), cfg));
if !type_name.namespace.is_empty() {
for def in reader.get_type_def(type_name) {
for def in reader.get_type_def(type_name.namespace, type_name.name) {
if def != row {
type_def_cfg_combine(reader, def, &[], cfg);
}
}
}
}
TypeKind::Delegate => signature_cfg_combine(reader, &reader.method_def_signature(type_def_invoke_method(reader, row), generics), cfg),
TypeKind::Delegate => signature_cfg_combine(reader, &type_def_invoke_method(row).signature(generics), cfg),
_ => {}
}
}
}

pub fn signature_cfg<'a>(reader: &'a Reader, method: MethodDef) -> Cfg<'a> {
pub fn signature_cfg(reader: &Reader, method: MethodDef) -> Cfg {
let mut cfg = Cfg::default();
signature_cfg_combine(reader, &reader.method_def_signature(method, &[]), &mut cfg);
cfg_add_attributes(reader, &mut cfg, method);
signature_cfg_combine(reader, &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 cfg_add_attributes<R: AsRow + Into<HasAttribute>>(reader: &Reader, cfg: &mut Cfg, row: R) {
for attribute in reader.attributes(row) {
match reader.attribute_name(attribute) {
fn cfg_add_attributes<R: AsRow + Into<HasAttribute>>(cfg: &mut Cfg, row: R) {
for attribute in row.attributes() {
match attribute.name() {
"SupportedArchitectureAttribute" => {
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(value) = **value {
if value & 1 == 1 {
cfg.arches.insert("x86");
Expand Down
Loading

0 comments on commit 4c234b5

Please sign in to comment.