calculating dependencies
This commit is contained in:
parent
211605c20c
commit
d1c0520316
195
src/lib.rs
195
src/lib.rs
|
@ -22,20 +22,19 @@ pub mod sdk {
|
|||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
use rayon::prelude::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||
|
||||
use crate::{
|
||||
global_tables::objects::{FindClass, GOBJECTS},
|
||||
v2_types::{
|
||||
any_type::{self, AnyProperty},
|
||||
any_type::{self, AnyField, AnyObject, AnyProperty, AnyStruct},
|
||||
traits::{
|
||||
AsUObject, StaticClass, UArrayPropertyTrait, UBytePropertyTrait,
|
||||
UEnumPropertyTrait, UEnumTrait, UFunctionTrait, UObjectNonConst,
|
||||
UObjectPropertyBaseTrait, UObjectTrait, UPropertyTrait, UStructNonConst,
|
||||
UStructPropertyTrait, UStructTrait,
|
||||
},
|
||||
EFunctionFlags, EPropertyFlags, UAnyType, UClass, UEnum, UFunction, UObject,
|
||||
UScriptStruct, UStruct,
|
||||
EFunctionFlags, EPropertyFlags, UAnyType, UClass, UEnum, UFunction, UObject, UStruct,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -86,23 +85,18 @@ pub mod sdk {
|
|||
pub struct Package {
|
||||
package: UObject,
|
||||
objects: Vec<UObject>,
|
||||
dependencies: Vec<UObject>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProcessedPackage {
|
||||
pub package: UObject,
|
||||
pub types: HashMap<UObject, Types>,
|
||||
pub package_dependencies: Vec<UObject>,
|
||||
pub package_dependencies: HashMap<UObject, Vec<UObject>>,
|
||||
}
|
||||
|
||||
impl Package {
|
||||
pub fn new(package: UObject, objects: Vec<UObject>) -> Self {
|
||||
Self {
|
||||
package,
|
||||
objects,
|
||||
dependencies: Vec::new(),
|
||||
}
|
||||
Self { package, objects }
|
||||
}
|
||||
|
||||
pub fn process(self) -> ProcessedPackage {
|
||||
|
@ -110,35 +104,47 @@ pub mod sdk {
|
|||
.objects
|
||||
.par_iter()
|
||||
.filter_map(|&object| {
|
||||
let ty = UAnyType::from_uobject(object.as_uobject());
|
||||
log::trace!("ty: {ty:?}");
|
||||
|
||||
match ty {
|
||||
UAnyType::UClass(class) => {
|
||||
if let Ok(class) = self.process_struct(unsafe { class.cast() }) {
|
||||
return Some((object, Types::Class(class)));
|
||||
match AnyObject::from_object(object) {
|
||||
AnyObject::Field(field) => match AnyField::from_field(field) {
|
||||
AnyField::Enum(enm) => {
|
||||
if let Ok(enm) = Self::process_enum(enm) {
|
||||
return Some((object, Types::Enum(enm)));
|
||||
}
|
||||
}
|
||||
}
|
||||
UAnyType::UScriptStruct(class) => {
|
||||
if let Ok(class) = self.process_struct(unsafe { class.cast() }) {
|
||||
return Some((object, Types::Class(class)));
|
||||
}
|
||||
}
|
||||
UAnyType::UEnum(obj) => {
|
||||
if let Ok(enm) = Self::process_enum(obj) {
|
||||
return Some((object, Types::Enum(enm)));
|
||||
}
|
||||
}
|
||||
AnyField::Struct(strt) => match AnyStruct::from_struct(strt) {
|
||||
strt @ AnyStruct::ScriptStruct(_) | strt @ AnyStruct::Class(_) => {
|
||||
if let Ok(class) = self.process_struct(unsafe { strt.cast() }) {
|
||||
return Some((object, Types::Class(class)));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
None
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let mut dependencies = types
|
||||
.iter()
|
||||
.filter_map(|(_, ty)| match ty {
|
||||
Types::Class(class) => Some(class.referenced_types()),
|
||||
_ => None,
|
||||
})
|
||||
.map(|refs| refs.into_iter())
|
||||
.flatten()
|
||||
.fold_into_packages();
|
||||
|
||||
// remove any objects in Self
|
||||
dependencies.remove(&self.package);
|
||||
|
||||
ProcessedPackage {
|
||||
package: self.package,
|
||||
types,
|
||||
package_dependencies: self.dependencies,
|
||||
package_dependencies: dependencies,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,25 +152,20 @@ pub mod sdk {
|
|||
let name = strct
|
||||
.get_name()
|
||||
.context("failed to get struct or class name")?;
|
||||
let is_struct = strct.is_a(&UScriptStruct::static_class().unwrap());
|
||||
let full_name = strct
|
||||
.get_full_name()
|
||||
.context("failed to get struct or class full name")?;
|
||||
let is_class = strct.is_a(&UClass::static_class().unwrap());
|
||||
|
||||
// process outers for classes
|
||||
if !is_struct {
|
||||
if let Some(outer) = strct.outer() {
|
||||
if outer.is_a(&UStruct::static_class().unwrap()) {
|
||||
// depend on this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let super_struct = if let Some(spr) = *strct.super_field() && spr != strct {
|
||||
if spr.package_object() != self.package {
|
||||
log::warn!("encountered external dependency");
|
||||
// TODO: return dependency on strct.package_object()
|
||||
}
|
||||
let super_struct = if let Some(spr) = *strct.super_field() {
|
||||
if spr != strct {
|
||||
Some(spr)
|
||||
} else {None};
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (fields, methods) = self.process_children(strct)?;
|
||||
|
||||
|
@ -175,6 +176,7 @@ pub mod sdk {
|
|||
super_class: super_struct,
|
||||
fields,
|
||||
methods,
|
||||
full_name,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -466,14 +468,46 @@ pub mod sdk {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Sdk {}
|
||||
trait FoldIntoPackages: Iterator<Item = UObject> + Sized {
|
||||
fn fold_into_packages(self) -> HashMap<UObject, Vec<UObject>> {
|
||||
self.map(|obj| (obj.package_object(), obj)).fold(
|
||||
HashMap::<UObject, Vec<UObject>>::new(),
|
||||
|mut acc, (pkg, obj)| {
|
||||
match acc.entry(pkg) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
entry.get_mut().push(obj);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(vec![obj]);
|
||||
}
|
||||
}
|
||||
|
||||
acc
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FoldIntoPackages for T where T: Iterator<Item = UObject> {}
|
||||
|
||||
pub struct Sdk {
|
||||
pub packages: HashMap<UObject, ProcessedPackage>,
|
||||
}
|
||||
|
||||
impl Sdk {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
let packages = Self::package_objects();
|
||||
|
||||
let packages = packages
|
||||
.into_par_iter()
|
||||
.map(|pkg| pkg.process())
|
||||
.map(|pkg| (pkg.package, pkg))
|
||||
.collect();
|
||||
|
||||
Self { packages }
|
||||
}
|
||||
|
||||
pub fn package_objects(&self) -> Vec<Package> {
|
||||
pub fn package_objects() -> Vec<Package> {
|
||||
let gobjects = GOBJECTS.read().unwrap();
|
||||
let objects = gobjects.as_objects().unwrap();
|
||||
|
||||
|
@ -482,22 +516,7 @@ pub mod sdk {
|
|||
// ensure item contains object
|
||||
.filter_map(|item| item.object())
|
||||
// get package object
|
||||
.map(|obj| (obj.package_object(), obj))
|
||||
.fold(
|
||||
HashMap::<UObject, Vec<UObject>>::new(),
|
||||
|mut acc, (pkg, obj)| {
|
||||
match acc.entry(pkg) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
entry.get_mut().push(obj);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(vec![obj]);
|
||||
}
|
||||
}
|
||||
|
||||
acc
|
||||
},
|
||||
);
|
||||
.fold_into_packages();
|
||||
|
||||
sorted_objects
|
||||
.into_iter()
|
||||
|
@ -654,6 +673,22 @@ pub mod sdk {
|
|||
Class(UStruct),
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn referenced_type(&self) -> Option<UObject> {
|
||||
match self {
|
||||
Type::Ptr(t) | Type::Ref(t) | Type::Array(t) | Type::RawArray { ty: t, .. } => {
|
||||
t.referenced_type()
|
||||
}
|
||||
Type::WeakPtr(o) | Type::SoftPtr(o) | Type::LazyPtr(o) | Type::AssetPtr(o) => {
|
||||
Some(o.as_uobject())
|
||||
}
|
||||
Type::Class(o) => Some(o.as_uobject()),
|
||||
Type::Primitive(_) | Type::Name | Type::String | Type::Text => None,
|
||||
Type::Enum { enum_type, .. } => Some(enum_type.as_uobject()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClassField {
|
||||
pub offset: u32,
|
||||
|
@ -683,11 +718,41 @@ pub mod sdk {
|
|||
pub is_class: bool,
|
||||
pub size: u32,
|
||||
pub name: String,
|
||||
pub full_name: String,
|
||||
pub super_class: Option<UStruct>,
|
||||
pub fields: Vec<ClassField>,
|
||||
pub methods: Vec<ClassMethod>,
|
||||
}
|
||||
|
||||
impl Class {
|
||||
pub fn referenced_types(&self) -> Vec<UObject> {
|
||||
let mut types = Vec::new();
|
||||
self.super_class.map(|obj| types.push(obj.as_uobject()));
|
||||
|
||||
for field in &self.fields {
|
||||
types.extend(field.ty.referenced_type());
|
||||
}
|
||||
|
||||
for method in &self.methods {
|
||||
types.extend(
|
||||
method
|
||||
.return_type
|
||||
.as_ref()
|
||||
.and_then(|ty| ty.referenced_type()),
|
||||
);
|
||||
types.extend(
|
||||
method
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|param| ¶m.ty)
|
||||
.filter_map(|ty| ty.referenced_type()),
|
||||
);
|
||||
}
|
||||
|
||||
types
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Types {
|
||||
Class(Class),
|
||||
|
|
|
@ -804,6 +804,10 @@ pub mod traits {
|
|||
.unwrap_or(self.as_uobject())
|
||||
}
|
||||
|
||||
fn is_in_package(&self, package: super::UObject) -> bool {
|
||||
self.package_object() == package
|
||||
}
|
||||
|
||||
fn is_a(&self, other: &super::UClass) -> bool {
|
||||
self.class()
|
||||
.map(|class| class.iter_super_classes().contains(other))
|
||||
|
|
Loading…
Reference in a new issue