Skip to content

Commit 30e0fbb

Browse files
authored
Simplify code generation (#2686)
1 parent 22de1c9 commit 30e0fbb

File tree

19 files changed

+98
-117
lines changed

19 files changed

+98
-117
lines changed

crates/libs/bindgen/src/metadata.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub enum AsyncKind {
8080
pub struct Guid(pub u32, pub u16, pub u16, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8);
8181

8282
impl Guid {
83-
pub fn from_args(args: &[(String, Value)]) -> Self {
83+
pub fn from_args(args: &[(&str, Value)]) -> Self {
8484
fn unwrap_u32(value: &Value) -> u32 {
8585
match value {
8686
Value::U32(value) => *value,
@@ -442,9 +442,7 @@ pub fn type_interfaces(ty: &Type) -> Vec<Interface> {
442442
// This will both sort the results and should make finding dupes faster
443443
fn walk(result: &mut Vec<Interface>, parent: &Type, is_base: bool) {
444444
if let Type::TypeDef(row, generics) = parent {
445-
for imp in row.interface_impls() {
446-
let mut child = Interface { ty: imp.ty(generics), kind: if imp.has_attribute("DefaultAttribute") { InterfaceKind::Default } else { InterfaceKind::None } };
447-
445+
for mut child in type_def_interfaces(*row, generics) {
448446
child.kind = if !is_base && child.kind == InterfaceKind::Default {
449447
InterfaceKind::Default
450448
} else if child.kind == InterfaceKind::Overridable {
@@ -482,8 +480,7 @@ pub fn type_interfaces(ty: &Type) -> Vec<Interface> {
482480
"StaticAttribute" | "ActivatableAttribute" => {
483481
for (_, arg) in attribute.args() {
484482
if let Value::TypeName(type_name) = arg {
485-
let type_name = parse_type_name(&type_name);
486-
let def = row.reader().get_type_def(type_name.0, type_name.1).next().expect("Type not found");
483+
let def = row.reader().get_type_def(type_name.namespace, type_name.name).next().expect("Type not found");
487484
result.push(Interface { ty: Type::TypeDef(def, Vec::new()), kind: InterfaceKind::Static });
488485
break;
489486
}
@@ -498,7 +495,7 @@ pub fn type_interfaces(ty: &Type) -> Vec<Interface> {
498495
result
499496
}
500497

501-
fn type_name<'a>(ty: &Type) -> &'a str {
498+
fn type_name(ty: &Type) -> &str {
502499
match ty {
503500
Type::TypeDef(row, _) => row.name(),
504501
_ => "",
@@ -657,8 +654,15 @@ pub fn type_def_has_packing(row: TypeDef) -> bool {
657654
}
658655
}
659656

657+
pub fn type_def_interfaces(def: TypeDef, generics: &[Type]) -> impl Iterator<Item = Interface> + '_ {
658+
def.interface_impls().map(|imp| {
659+
let kind = if imp.has_attribute("DefaultAttribute") { InterfaceKind::Default } else { InterfaceKind::None };
660+
Interface { kind, ty: imp.ty(generics) }
661+
})
662+
}
663+
660664
pub fn type_def_default_interface(row: TypeDef) -> Option<Type> {
661-
row.interface_impls().find_map(move |row| if row.has_attribute("DefaultAttribute") { Some(row.ty(&[])) } else { None })
665+
type_def_interfaces(row, &[]).find_map(move |interface| if interface.kind == InterfaceKind::Default { Some(interface.ty) } else { None })
662666
}
663667

664668
fn type_signature(ty: &Type) -> String {
@@ -792,7 +796,7 @@ pub fn type_def_vtables(row: TypeDef) -> Vec<Type> {
792796
}
793797
} else {
794798
let mut next = row;
795-
while let Some(base) = type_def_interfaces(next, &[]).next() {
799+
while let Some(base) = next.interface_impls().map(move |imp| imp.ty(&[])).next() {
796800
match base {
797801
Type::TypeDef(row, _) => {
798802
next = row;
@@ -813,7 +817,3 @@ pub fn type_def_vtables(row: TypeDef) -> Vec<Type> {
813817
}
814818
result
815819
}
816-
817-
pub fn type_def_interfaces(row: TypeDef, generics: &[Type]) -> impl Iterator<Item = Type> + '_ {
818-
row.interface_impls().map(move |row| row.ty(generics))
819-
}

crates/libs/bindgen/src/rdl/from_reader.rs

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::tokens::{quote, to_ident, TokenStream};
33
use crate::{rdl, Error, Result, Tree};
44
use metadata::*;
55

6-
pub fn from_reader(reader: &metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
6+
pub fn from_reader(reader: &'static metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
77
let dialect = match config.remove("type") {
88
Some("winrt") => Dialect::WinRT,
99
Some("win32") => Dialect::Win32,
@@ -30,7 +30,7 @@ pub fn from_reader(reader: &metadata::Reader, mut config: std::collections::BTre
3030

3131
fn gen_split(writer: &Writer) -> Result<()> {
3232
let tree = Tree::new(writer.reader);
33-
let directory = crate::directory(writer.output);
33+
let directory = crate::directory(&writer.output);
3434

3535
// TODO: parallelize
3636
for tree in tree.flatten() {
@@ -48,7 +48,7 @@ fn gen_split(writer: &Writer) -> Result<()> {
4848
fn gen_file(writer: &Writer) -> Result<()> {
4949
let tree = Tree::new(writer.reader);
5050
let tokens = writer.tree(&tree);
51-
writer.write_to_file(writer.output, tokens)
51+
writer.write_to_file(&writer.output, tokens)
5252
}
5353

5454
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -57,21 +57,21 @@ enum Dialect {
5757
WinRT,
5858
}
5959

60-
struct Writer<'a> {
61-
reader: &'a metadata::Reader,
62-
namespace: &'a str,
60+
struct Writer {
61+
reader: &'static metadata::Reader,
62+
namespace: &'static str,
6363
dialect: Dialect,
6464
split: bool,
65-
output: &'a str,
65+
output: String,
6666
}
6767

68-
impl<'a> Writer<'a> {
69-
fn new(reader: &'a metadata::Reader, output: &'a str, dialect: Dialect) -> Self {
70-
Self { reader, namespace: "", output, dialect, split: false }
68+
impl Writer {
69+
fn new(reader: &'static metadata::Reader, output: &str, dialect: Dialect) -> Self {
70+
Self { reader, namespace: "", output: output.to_string(), dialect, split: false }
7171
}
7272

73-
fn with_namespace(&self, namespace: &'a str) -> Self {
74-
Self { reader: self.reader, namespace, dialect: self.dialect, output: self.output, split: self.split }
73+
fn with_namespace(&self, namespace: &'static str) -> Self {
74+
Self { reader: self.reader, namespace, dialect: self.dialect, output: self.output.clone(), split: self.split }
7575
}
7676

7777
fn write_to_file(&self, output: &str, tokens: TokenStream) -> Result<()> {
@@ -90,7 +90,7 @@ impl<'a> Writer<'a> {
9090
//crate::write_to_file(output, tokens.into_string())
9191
}
9292

93-
fn tree(&self, tree: &'a Tree) -> TokenStream {
93+
fn tree(&self, tree: &Tree) -> TokenStream {
9494
let items = self.items(tree);
9595

9696
if self.split {
@@ -128,7 +128,7 @@ impl<'a> Writer<'a> {
128128
}
129129
}
130130

131-
fn items(&self, tree: &'a Tree) -> TokenStream {
131+
fn items(&self, tree: &Tree) -> TokenStream {
132132
let mut functions = vec![];
133133
let mut constants = vec![];
134134
let mut types = vec![];
@@ -286,12 +286,11 @@ impl<'a> Writer<'a> {
286286
// TODO: then list default interface first
287287
// Then everything else
288288

289-
for imp in def.interface_impls() {
290-
let ty = imp.ty(generics);
291-
if imp.has_attribute("DefaultAttribute") {
292-
types.insert(0, self.ty(&ty));
289+
for interface in type_def_interfaces(def, generics) {
290+
if interface.kind == InterfaceKind::Default {
291+
types.insert(0, self.ty(&interface.ty));
293292
} else {
294-
types.push(self.ty(&ty));
293+
types.push(self.ty(&interface.ty));
295294
}
296295
}
297296

@@ -358,8 +357,7 @@ impl<'a> Writer<'a> {
358357
}
359358
}
360359

361-
metadata::Type::TypeRef(code) => {
362-
let type_name = code.type_name();
360+
metadata::Type::TypeRef(type_name) => {
363361
let namespace = self.namespace(type_name.namespace);
364362
let name = to_ident(type_name.name);
365363
quote! { #namespace #name }

crates/libs/bindgen/src/rust/cfg.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,12 @@ pub fn type_def_cfg_impl(def: TypeDef, generics: &[Type]) -> Cfg {
5858

5959
combine(def, generics, &mut cfg);
6060

61-
for def in type_def_vtables(def) {
62-
if let Type::TypeDef(def, generics) = def {
61+
for interface in type_interfaces(&Type::TypeDef(def, generics.to_vec())) {
62+
if let Type::TypeDef(def, generics) = interface.ty {
6363
combine(def, &generics, &mut cfg);
6464
}
6565
}
6666

67-
if def.flags().contains(TypeAttributes::WindowsRuntime) {
68-
for interface in type_def_interfaces(def, generics) {
69-
if let Type::TypeDef(def, generics) = interface {
70-
combine(def, &generics, &mut cfg);
71-
}
72-
}
73-
}
74-
7567
cfg_add_attributes(&mut cfg, def);
7668
cfg
7769
}
@@ -156,6 +148,7 @@ pub fn type_cfg(ty: &Type) -> Cfg {
156148
type_cfg_combine(ty, &mut cfg);
157149
cfg
158150
}
151+
159152
fn type_cfg_combine(ty: &Type, cfg: &mut Cfg) {
160153
match ty {
161154
Type::TypeDef(row, generics) => type_def_cfg_combine(*row, generics, cfg),

crates/libs/bindgen/src/rust/classes.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::*;
22

33
pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream {
44
if writer.sys {
5-
if type_def_has_default_interface(def) {
5+
if def.interface_impls().next().is_some() {
66
let name = to_ident(def.name());
77
quote! {
88
pub type #name = *mut ::core::ffi::c_void;
@@ -64,7 +64,7 @@ fn gen_class(writer: &Writer, def: TypeDef) -> TokenStream {
6464
_ => None,
6565
});
6666

67-
if type_def_has_default_interface(def) {
67+
if def.interface_impls().next().is_some() {
6868
let new = if type_def_has_default_constructor(def) {
6969
quote! {
7070
pub fn new() -> ::windows_core::Result<Self> {
@@ -172,10 +172,6 @@ fn type_def_has_default_constructor(row: TypeDef) -> bool {
172172
false
173173
}
174174

175-
fn type_def_has_default_interface(row: TypeDef) -> bool {
176-
row.interface_impls().any(|imp| imp.has_attribute("DefaultAttribute"))
177-
}
178-
179175
fn type_is_exclusive(ty: &Type) -> bool {
180176
match ty {
181177
Type::TypeDef(row, _) => type_def_is_exclusive(*row),

crates/libs/bindgen/src/rust/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::{Error, Result, Tree};
2121
use cfg::*;
2222
use rayon::prelude::*;
2323

24-
pub fn from_reader(reader: &metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
24+
pub fn from_reader(reader: &'static metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
2525
let mut writer = Writer::new(reader, output);
2626
writer.package = config.remove("package").is_some();
2727
writer.flatten = config.remove("flatten").is_some();
@@ -56,7 +56,7 @@ fn gen_file(writer: &Writer) -> Result<()> {
5656

5757
if writer.flatten {
5858
let tokens = standalone::standalone_imp(writer);
59-
crate::write_to_file(writer.output, try_format(writer, &tokens))
59+
crate::write_to_file(&writer.output, try_format(writer, &tokens))
6060
} else {
6161
let mut tokens = String::new();
6262
let root = Tree::new(writer.reader);
@@ -65,12 +65,12 @@ fn gen_file(writer: &Writer) -> Result<()> {
6565
tokens.push_str(&namespace(writer, tree));
6666
}
6767

68-
crate::write_to_file(writer.output, try_format(writer, &tokens))
68+
crate::write_to_file(&writer.output, try_format(writer, &tokens))
6969
}
7070
}
7171

7272
fn gen_package(writer: &Writer) -> Result<()> {
73-
let directory = crate::directory(writer.output);
73+
let directory = crate::directory(&writer.output);
7474
let root = Tree::new(writer.reader);
7575
let mut root_len = 0;
7676

crates/libs/bindgen/src/rust/writer.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use super::*;
22

33
#[derive(Clone)]
4-
pub struct Writer<'a> {
5-
pub reader: &'a Reader,
6-
pub output: &'a str,
7-
pub namespace: &'a str,
4+
pub struct Writer {
5+
pub reader: &'static Reader,
6+
pub output: String,
7+
pub namespace: &'static str,
88
pub implement: bool, // TODO: ideally we can use this to generate implementation traits on the fly and
99
// and have a single interface definition macro for consumption that expands to include
1010
// impl traits when the `implement` cfg flag is set and then this writer option would be
@@ -20,11 +20,11 @@ pub struct Writer<'a> {
2020
pub no_inner_attributes: bool, // skips the inner attributes at the start of the file
2121
}
2222

23-
impl<'a> Writer<'a> {
24-
pub fn new(reader: &'a Reader, output: &'a str) -> Self {
23+
impl Writer {
24+
pub fn new(reader: &'static Reader, output: &str) -> Self {
2525
Self {
2626
reader,
27-
output,
27+
output: output.to_string(),
2828
namespace: "",
2929
implement: false,
3030
std: false,
@@ -403,7 +403,7 @@ impl<'a> Writer<'a> {
403403
quote! { #arch #features }
404404
}
405405

406-
fn cfg_features_imp(&self, cfg: &'a Cfg, namespace: &'a str) -> Vec<&'a str> {
406+
fn cfg_features_imp(&self, cfg: &Cfg, namespace: &str) -> Vec<&'static str> {
407407
let mut compact = Vec::<&'static str>::new();
408408
if self.package {
409409
for feature in cfg.types.keys() {
@@ -568,7 +568,7 @@ impl<'a> Writer<'a> {
568568
let mut async_generics = generics.to_vec();
569569

570570
if kind == AsyncKind::None {
571-
for interface in type_def_interfaces(def, generics) {
571+
for interface in def.interface_impls().map(move |imp| imp.ty(generics)) {
572572
if let Type::TypeDef(interface_def, interface_generics) = &interface {
573573
kind = type_def_async_kind(*interface_def);
574574
if kind != AsyncKind::None {

crates/libs/bindgen/src/tree.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use super::*;
22

33
#[derive(Debug)]
4-
pub struct Tree<'a> {
5-
pub namespace: &'a str,
6-
pub nested: std::collections::BTreeMap<&'a str, Tree<'a>>,
4+
pub struct Tree {
5+
pub namespace: &'static str,
6+
pub nested: std::collections::BTreeMap<&'static str, Tree>,
77
}
88

9-
impl<'a> Tree<'a> {
10-
pub fn new(reader: &'a metadata::Reader) -> Self {
9+
impl Tree {
10+
pub fn new(reader: &'static metadata::Reader) -> Self {
1111
let mut tree = Tree::from_namespace("");
1212
for ns in reader.namespaces() {
1313
if reader.includes_namespace(ns) {
@@ -17,10 +17,10 @@ impl<'a> Tree<'a> {
1717
tree
1818
}
1919

20-
fn from_namespace(namespace: &'a str) -> Self {
20+
fn from_namespace(namespace: &'static str) -> Self {
2121
Self { namespace, nested: std::collections::BTreeMap::new() }
2222
}
23-
fn insert_namespace(&mut self, namespace: &'a str, pos: usize) -> &mut Self {
23+
fn insert_namespace(&mut self, namespace: &'static str, pos: usize) -> &mut Self {
2424
if let Some(next) = namespace[pos..].find('.') {
2525
let next = pos + next;
2626
self.nested.entry(&namespace[pos..next]).or_insert_with(|| Self::from_namespace(&namespace[..next])).insert_namespace(namespace, next + 1)

crates/libs/bindgen/src/winmd/from_reader.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,15 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap
3636

3737
for generic in def.generics() {
3838
writer.tables.GenericParam.push(writer::GenericParam {
39-
Number: generic.number(),
39+
Number: generic.number(), // TODO: isn't this just going to be incremental?
4040
Flags: 0,
4141
Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1).encode(),
4242
Name: writer.strings.insert(generic.name()),
4343
});
4444
}
4545

46-
for imp in def.interface_impls() {
47-
let ty = imp.ty(generics);
48-
let ty = winmd_type(&ty);
46+
for interface in metadata::type_def_interfaces(def, generics) {
47+
let ty = winmd_type(&interface.ty);
4948

5049
let reference = match &ty {
5150
winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => writer.insert_type_ref(&type_name.namespace, &type_name.name),
@@ -122,7 +121,7 @@ fn winmd_type(ty: &metadata::Type) -> winmd::Type {
122121
metadata::Type::PCSTR => winmd::Type::PCSTR,
123122
metadata::Type::PCWSTR => winmd::Type::PCWSTR,
124123
metadata::Type::BSTR => winmd::Type::BSTR,
125-
metadata::Type::TypeName => winmd::Type::TypeName,
124+
metadata::Type::Type => winmd::Type::Type,
126125
metadata::Type::TypeDef(def, generics) => winmd::Type::TypeRef(winmd::TypeName { namespace: def.namespace().to_string(), name: def.name().to_string(), generics: generics.iter().map(winmd_type).collect() }),
127126
metadata::Type::GenericParam(generic) => winmd::Type::GenericParam(generic.number()),
128127
metadata::Type::ConstRef(ty) => winmd::Type::ConstRef(Box::new(winmd_type(ty))),

crates/libs/bindgen/src/winmd/verify.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn verify(reader: &metadata::Reader) -> crate::Result<()> {
3636

3737
fn not_type_ref(ty: &metadata::Type) -> crate::Result<()> {
3838
if let metadata::Type::TypeRef(ty) = ty {
39-
return Err(crate::Error::new(&format!("missing type definition `{}`", ty.type_name())));
39+
return Err(crate::Error::new(&format!("missing type definition `{}`", ty)));
4040
}
4141
Ok(())
4242
}

crates/libs/bindgen/src/winmd/writer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl Writer {
234234
usize_blob(1, blob); // count
235235
usize_blob(*bounds, blob);
236236
}
237-
Type::TypeName => {
237+
Type::Type => {
238238
let code = self.insert_type_ref("System", "Type");
239239
blob.push(metadata::ELEMENT_TYPE_CLASS);
240240
usize_blob(code as usize, blob);

0 commit comments

Comments
 (0)