Skip to content

Commit

Permalink
natural type sort
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Dec 3, 2024
1 parent f892d0a commit 01763ef
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 17 deletions.
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/libraries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn combine_libraries(

if flags.contains(PInvokeAttributes::CallConvPlatformapi) {
let arches = ty.method.arches();
let params = if arches.is_empty() || arches.contains("x86") {
let params = if (arches == 0) || (arches & 1 == 1) {
ty.method.signature(ty.namespace, &[]).size()
} else {
0
Expand Down Expand Up @@ -67,7 +67,7 @@ fn cpp_fn(types: &[Type]) -> Option<CppFn> {

for ty in &functions {
let arches = ty.method.arches();
if arches.is_empty() || arches.contains("x86") {
if (arches == 0) || (arches & 1 == 1) {
return Some(ty.clone());
}
}
Expand Down
16 changes: 15 additions & 1 deletion crates/libs/bindgen/src/type_name.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
use super::*;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct TypeName(pub &'static str, pub &'static str);

impl Ord for TypeName {
fn cmp(&self, other: &Self) -> Ordering {
// Type names are sorted before namespaces. The `Type` sort order depends on this.
// This is more efficient in general as many types typically share a namespace.
(self.1, self.0).cmp(&(other.1, other.0))
}
}

impl PartialOrd for TypeName {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl TypeName {
pub const Object: Self = Self("System", "Object");
pub const GUID: Self = Self("System", "Guid");
Expand Down
47 changes: 46 additions & 1 deletion crates/libs/bindgen/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub use method::*;
pub use r#enum::*;
pub use r#struct::*;

#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Type {
CppFn(CppFn),
Class(Class),
Expand Down Expand Up @@ -80,6 +80,18 @@ pub enum Type {
BSTR,
}

impl Ord for Type {
fn cmp(&self, other: &Self) -> Ordering {
self.sort_key().cmp(&(other.sort_key()))
}
}

impl PartialOrd for Type {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

#[derive(PartialEq)]
pub enum Remap {
Type(Type),
Expand All @@ -88,6 +100,39 @@ pub enum Remap {
}

impl Type {
fn sort_key(&self) -> (bool, TypeName, i32, i32) {
// This sorts types as follows:
// 1. functions are placed first
// 2. type name
// 3. type namespace
// 4. architecture
// 5. overloaded types

let kind = match self {
Self::CppFn(..) => 0,
Self::Class(..) => 1,
Self::Interface(..) => 2,
Self::CppInterface(..) => 3,
Self::Delegate(..) => 4,
Self::CppDelegate(..) => 5,
Self::Enum(..) => 6,
Self::CppEnum(..) => 7,
Self::Struct(..) => 8,
Self::CppStruct(..) => 9,
Self::CppConst(..) => 10,
_ => -1,
};

let arches = match self {
Self::CppFn(ty) => ty.method.arches(),
Self::CppStruct(ty) => ty.def.arches(),
Self::CppDelegate(ty) => ty.def.arches(),
_ => 0,
};

(kind != 0, self.type_name(), arches, kind)
}

fn is_intrinsic(&self) -> bool {
matches!(
self,
Expand Down
17 changes: 4 additions & 13 deletions crates/libs/bindgen/src/winmd/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub trait HasAttributes {
fn find_attribute(&self, name: &str) -> Option<Attribute>;
fn has_attribute(&self, name: &str) -> bool;
fn guid_attribute(&self) -> Option<GUID>;
fn arches(&self) -> HashSet<&'static str>;
fn arches(&self) -> i32;
}

impl<R: AsRow + Into<HasAttribute>> HasAttributes for R {
Expand Down Expand Up @@ -142,21 +142,12 @@ impl<R: AsRow + Into<HasAttribute>> HasAttributes for R {
})
}

fn arches(&self) -> HashSet<&'static str> {
let mut arches = HashSet::new();
fn arches(&self) -> i32 {
let mut arches = 0;

if let Some(attribute) = self.find_attribute("SupportedArchitectureAttribute") {
if let Some((_, Value::I32(value))) = attribute.args().first() {
if value & 1 == 1 {
arches.insert("x86");
}
if value & 2 == 2 {
arches.insert("x86_64");
arches.insert("arm64ec");
}
if value & 4 == 4 {
arches.insert("aarch64");
}
arches = *value;
}
}

Expand Down

0 comments on commit 01763ef

Please sign in to comment.