Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify metadata reader #2682

Merged
merged 7 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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