Skip to content

Commit

Permalink
Harden nested type discovery (#3471)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Feb 3, 2025
1 parent e135ae6 commit d993221
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 17 deletions.
4 changes: 4 additions & 0 deletions crates/libs/bindgen/src/tables/type_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ impl TypeDef {
self.file().equal_range(2, self.index() + 1).next()
}

pub fn nested(&self) -> Option<NestedClass> {
self.file().equal_range(0, self.index() + 1).next()
}

pub fn underlying_type(&self) -> Type {
let field = self.fields().next().unwrap();
if let Some(constant) = field.constant() {
Expand Down
4 changes: 4 additions & 0 deletions crates/libs/bindgen/src/winmd/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,8 @@ flags!(TypeAttributes, u32);
impl TypeAttributes {
pub const ExplicitLayout: Self = Self(0x10);
pub const WindowsRuntime: Self = Self(0x4000);

pub fn is_nested(&self) -> bool {
(self.0 & 0x00000006) != 0
}
}
52 changes: 35 additions & 17 deletions crates/libs/bindgen/src/winmd/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,23 @@ impl Reader {
}

for def in file.table::<TypeDef>() {
let type_name = def.type_name();
let flags = def.flags();

if type_name.namespace().is_empty() {
if flags.is_nested() || def.nested().is_some() {
// This skips the nested types as we've already retrieved them.
continue;
}

let type_name = def.type_name();

if Type::remap(type_name) != Remap::None {
continue;
}

let types = reader.0.entry(type_name.namespace()).or_default();
let category = Category::new(def);

if def.flags().contains(TypeAttributes::WindowsRuntime) {
if flags.contains(TypeAttributes::WindowsRuntime) {
let ty = match category {
Category::Attribute => continue,
Category::Class => Type::Class(Class { def }),
Expand All @@ -67,12 +69,12 @@ impl Reader {
}
};

insert(types, type_name.1, ty);
insert(types, type_name.name(), ty);
} else {
match category {
Category::Attribute => continue,
Category::Class => {
if type_name.1 == "Apis" {
if type_name.name() == "Apis" {
for method in def.methods() {
if let Some(map) = method.impl_map() {
// Skip inline and ordinal functions.
Expand All @@ -88,7 +90,7 @@ impl Reader {
types,
name,
Type::CppFn(CppFn {
namespace: def.namespace(),
namespace: type_name.namespace(),
method,
}),
);
Expand All @@ -100,18 +102,22 @@ impl Reader {
types,
name,
Type::CppConst(CppConst {
namespace: def.namespace(),
namespace: type_name.namespace(),
field,
}),
);
}
}
}
Category::Delegate => {
insert(types, type_name.1, Type::CppDelegate(CppDelegate { def }));
insert(
types,
type_name.name(),
Type::CppDelegate(CppDelegate { def }),
);
}
Category::Enum => {
insert(types, type_name.1, Type::CppEnum(CppEnum { def }));
insert(types, type_name.name(), Type::CppEnum(CppEnum { def }));

if !def.has_attribute("ScopedEnumAttribute") {
for field in def.fields() {
Expand All @@ -121,7 +127,7 @@ impl Reader {
types,
name,
Type::CppConst(CppConst {
namespace: def.namespace(),
namespace: type_name.namespace(),
field,
}),
);
Expand All @@ -130,7 +136,11 @@ impl Reader {
}
}
Category::Interface => {
insert(types, type_name.1, Type::CppInterface(CppInterface { def }));
insert(
types,
type_name.name(),
Type::CppInterface(CppInterface { def }),
);
}
Category::Struct => {
fn make(
Expand All @@ -147,19 +157,26 @@ impl Reader {
for (index, def) in
nested.get(&def).into_iter().flatten().enumerate()
{
ty.nested.insert(
def.name(),
make(*def, format!("{}_{index}", ty.name).leak(), nested),
);
// Only nested structs are supported. https://github.com/microsoft/windows-rs/issues/3468
if Category::new(*def) == Category::Struct {
ty.nested.insert(
def.name(),
make(
*def,
format!("{}_{index}", ty.name).leak(),
nested,
),
);
}
}

ty
}

insert(
types,
type_name.1,
Type::CppStruct(make(def, def.name(), &nested)),
type_name.name(),
Type::CppStruct(make(def, type_name.name(), &nested)),
);
}
};
Expand Down Expand Up @@ -189,6 +206,7 @@ impl Reader {
}
}

#[derive(PartialEq)]
enum Category {
Interface,
Class,
Expand Down

0 comments on commit d993221

Please sign in to comment.