removed deref impl as it was unsound

- started on sdk generator, can classify and sort objects into packages
- parse enums
This commit is contained in:
Janis 2023-04-18 01:07:07 +02:00
parent 41dbc1bdd0
commit f12f48c83f
2 changed files with 186 additions and 31 deletions

View file

@ -1,3 +1,178 @@
mod core_types; mod core_types;
pub mod global_tables; pub mod global_tables;
pub mod types; pub mod types;
pub mod sdk {
use std::{
collections::{hash_map::Entry, HashMap},
sync::Mutex,
};
use anyhow::Context;
use crate::{
global_tables::objects::{FindClass, GOBJECTS},
types::{traits::AsUObject, UAnyType, UClass, UEnum, UObject},
};
pub const UOBJECT: &'static str = "Class CoreUObject.Object";
pub const UCLASS: &'static str = "Class CoreUObject.Class";
pub const UFUNCTION: &'static str = "Class CoreUObject.Function";
pub const UFIELD: &'static str = "Class CoreUObject.Field";
pub const UENUM: &'static str = "Class CoreUObject.Enum";
pub const USTRUCT: &'static str = "Class CoreUObject.Struct";
pub const USCRIPTSTRUCT: &'static str = "Class CoreUObject.ScriptStruct";
struct ClassCache {
classes: Mutex<HashMap<String, UClass>>,
}
impl ClassCache {
pub fn new() -> Self {
Self {
classes: Mutex::new(HashMap::new()),
}
}
fn identify_uobject(&self, object: UObject) -> UAnyType {
if object.is_a(&self.find_class(UENUM).expect("uenum")) {
UAnyType::UEnum(object.into())
} else if object.is_a(&self.find_class(UFIELD).expect("ufield")) {
UAnyType::UField(object.into())
} else if object.is_a(&self.find_class(USTRUCT).expect("ustruct")) {
UAnyType::UStruct(object.into())
} else if object.is_a(&self.find_class(UFUNCTION).expect("ufunction")) {
UAnyType::UFunction(object.into())
} else if object.is_a(&self.find_class(UCLASS).expect("uclass")) {
UAnyType::UClass(object.into())
} else if object.is_a(&self.find_class(USCRIPTSTRUCT).expect("uscriptstruct")) {
UAnyType::UScriptStruct(object.into())
} else {
UAnyType::UObject(object)
}
}
pub fn cache_class(&mut self, class: UClass) -> anyhow::Result<()> {
let name = class.get_full_name()?;
self.classes.lock().unwrap().insert(name, class);
Ok(())
}
}
impl FindClass for ClassCache {
fn find_class<S>(&self, class_name: S) -> Option<UClass>
where
S: Into<String>,
{
let class_name = class_name.into();
let class = self.classes.lock().unwrap().get(&class_name).cloned();
match class {
class @ Some(_) => class,
None => match GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(&class_name)
{
Some(class) => {
self.classes
.lock()
.unwrap()
.insert(class_name, class.clone());
Some(class)
}
None => None,
},
}
}
}
pub struct Sdk {}
impl Sdk {
pub fn package_objects() -> HashMap<UObject, Vec<UObject>> {
let gobjects = GOBJECTS.read().unwrap();
let objects = gobjects.as_objects().unwrap();
let sorted_objects = objects
.iter()
// ensure item contains object
.filter_map(|item| item.object())
// get package object
.filter_map(|obj| obj.outermost().map(|pkg| (pkg, 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
},
);
sorted_objects
}
pub fn process_packages(packages: HashMap<UObject, Vec<UObject>>) -> anyhow::Result<()> {
let mut cache = ClassCache::new();
for (package, objects) in packages {
Self::process_package(&mut cache, package, objects)?;
}
Ok(())
}
fn process_package(
cache: &mut ClassCache,
package: UObject,
objects: Vec<UObject>,
) -> anyhow::Result<()> {
cache
.cache_class(package.class().context("package had no class")?)
.context("package not of any base type")?;
for object in objects {
cache
.cache_class(object.class().expect("object had no class?"))
.context("object not of any base type?")?;
let ty = cache.identify_uobject(object);
log::debug!("ty: {ty:?}");
match ty {
UAnyType::UObject(_) => {}
UAnyType::UClass(_) => {}
UAnyType::UField(_) => {}
UAnyType::UScriptStruct(_) => {}
UAnyType::UProperty(_) => {}
UAnyType::UEnum(obj) => Self::process_enum(obj),
UAnyType::UStruct(_) => {}
UAnyType::UFunction(_) => {}
}
}
Ok(())
}
fn process_enum(enm: UEnum) {
let names = enm
.get_names()
.iter()
.map(|name| name.get_name().unwrap_or("<invalid-name>".to_string()))
.collect::<Vec<_>>();
log::info!("enum: {}", enm.as_uobject().get_full_name_or_default());
log::info!("{names:#?}");
}
}
}

View file

@ -1,6 +1,6 @@
use anyhow::Context; use anyhow::Context;
use itertools::Itertools; use itertools::Itertools;
use std::{hash::Hash, ops::Deref, ptr::NonNull}; use std::{hash::Hash, ptr::NonNull};
use crate::core_types::{self, FName, TArray}; use crate::core_types::{self, FName, TArray};
@ -12,6 +12,9 @@ pub struct UObject {
inner: NonNull<core_types::UObject>, inner: NonNull<core_types::UObject>,
} }
unsafe impl Send for UObject {}
unsafe impl Sync for UObject {}
impl Eq for UObject {} impl Eq for UObject {}
impl PartialEq for UObject { impl PartialEq for UObject {
@ -36,25 +39,17 @@ pub struct UClass {
inner: NonNull<core_types::UClass>, inner: NonNull<core_types::UClass>,
} }
impl Deref for UClass {
type Target = UObject;
fn deref(&self) -> &Self::Target {
unsafe { std::mem::transmute(&self) }
}
}
impl Eq for UClass {} impl Eq for UClass {}
impl PartialEq for UClass { impl PartialEq for UClass {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.deref().eq(other) self.as_uobject().eq(&other.as_uobject())
} }
} }
impl Hash for UClass { impl Hash for UClass {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state); self.as_uobject().hash(state);
} }
} }
@ -64,25 +59,17 @@ pub struct UField {
inner: NonNull<core_types::UField>, inner: NonNull<core_types::UField>,
} }
impl Deref for UField {
type Target = UObject;
fn deref(&self) -> &Self::Target {
unsafe { std::mem::transmute(&self) }
}
}
impl Eq for UField {} impl Eq for UField {}
impl PartialEq for UField { impl PartialEq for UField {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.deref().eq(other) self.as_uobject().eq(&other.as_uobject())
} }
} }
impl Hash for UField { impl Hash for UField {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state); self.as_uobject().hash(state);
} }
} }
@ -262,16 +249,9 @@ impl Iterator for SuperClassIter {
type Item = UClass; type Item = UClass;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if let Some(next) = self if let Some(next) = self.class.super_struct().map(|spr| spr.as_uobject().into()) {
.class let item = core::mem::replace(&mut self.class, next);
.as_ref() Some(item)
.ustruct
.super_field
.map(|inner| inner.cast::<core_types::UClass>())
.map(|inner| UClass::new(inner))
{
self.class = next.clone();
Some(next)
} else { } else {
None None
} }