using pointer types now for every coreuobject type

This commit is contained in:
Janis 2023-04-20 03:35:31 +02:00
parent 724939e5da
commit f8f183c420
4 changed files with 121 additions and 62 deletions

View file

@ -1,6 +1,6 @@
use std::{ops::Index, ptr::NonNull, sync::RwLock};
use crate::core_types::FName;
use crate::fname::FName;
lazy_static::lazy_static! {
pub static ref GNAMES: RwLock<GNames> = RwLock::new(GNames::new());

View file

@ -1,8 +1,11 @@
use std::{ops::Index, ptr::NonNull, sync::RwLock};
use std::{cell::UnsafeCell, ops::Index, ptr::NonNull, sync::RwLock};
use rayon::prelude::ParallelIterator;
use crate::types;
use crate::v2_types::{
self,
traits::{AsUObject, UObjectTrait},
};
lazy_static::lazy_static! {
pub static ref GOBJECTS: RwLock<GObjects> = RwLock::new(GObjects::new());
@ -10,7 +13,7 @@ lazy_static::lazy_static! {
#[derive(Debug, Default)]
pub struct GObjects {
objects: Option<NonNull<ObjectArray>>,
objects: Option<NonNull<UnsafeCell<ObjectArray>>>,
}
impl GObjects {
@ -19,11 +22,12 @@ impl GObjects {
}
pub fn set_objects(&mut self, objects: NonNull<ObjectArray>) {
self.objects = Some(objects);
self.objects = Some(objects.cast());
}
pub fn as_objects(&self) -> Option<&ObjectArray> {
self.objects.map(|objects| unsafe { objects.as_ref() })
self.objects
.map(|objects| unsafe { &*objects.as_ref().get() })
}
}
@ -33,7 +37,7 @@ unsafe impl Sync for GObjects {}
#[repr(C)]
#[derive(Debug)]
pub struct ObjectArrayItem {
object: Option<NonNull<crate::core_types::UObject>>,
object: Option<v2_types::UObject>,
sn: u32,
}
@ -41,8 +45,8 @@ unsafe impl Send for ObjectArrayItem {}
unsafe impl Sync for ObjectArrayItem {}
impl ObjectArrayItem {
pub fn object(&self) -> Option<types::UObject> {
types::UObject::maybe_new(self.object)
pub fn object(&self) -> Option<v2_types::UObject> {
self.object
}
}
@ -233,22 +237,28 @@ pub mod par_iter {
}
pub trait FindClass {
fn find_class<S>(&self, class_name: S) -> Option<types::UClass>
fn find_class<S>(&self, class_name: S) -> Option<v2_types::UClass>
where
S: Into<String>;
}
impl FindClass for ObjectArray {
fn find_class<S>(&self, class_name: S) -> Option<types::UClass>
fn find_class<S>(&self, class_name: S) -> Option<v2_types::UClass>
where
S: Into<String>,
{
use crate::v2_types::traits::UObjectNonConst;
let class_name = class_name.into();
self.iter()
.filter_map(|item| item.object())
.filter(|object| object.get_full_name().unwrap() == class_name)
.map(|object| types::UClass::new(unsafe { object.cast() }))
.filter(|object| {
object
.get_full_name()
.map(|name| name == class_name)
.unwrap_or(false)
})
.map(|object| (unsafe { object.cast() }))
.next()
}
}

View file

@ -1,10 +1,10 @@
#![feature(const_trait_impl, const_ptr_as_ref, const_nonnull_new)]
mod core_types;
// mod core_types;
pub mod fname;
pub mod global_tables;
pub mod tarray;
pub mod types;
// pub mod types;
pub mod v2_types;
pub mod sdk {
@ -19,17 +19,12 @@ pub mod sdk {
use crate::{
global_tables::objects::{FindClass, GOBJECTS},
types::{traits::AsUObject, UAnyType, UClass, UEnum, UObject},
v2_types::{
traits::{AsUObject, UEnumTrait, UObjectNonConst, UObjectTrait},
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>>,
}
@ -41,24 +36,6 @@ pub mod sdk {
}
}
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);
@ -109,7 +86,7 @@ pub mod sdk {
// ensure item contains object
.filter_map(|item| item.object())
// get package object
.filter_map(|obj| obj.outermost().map(|pkg| (pkg, obj)))
.map(|obj| (obj.package_object(), obj))
.fold(
HashMap::<UObject, Vec<UObject>>::new(),
|mut acc, (pkg, obj)| {
@ -153,7 +130,7 @@ pub mod sdk {
.cache_class(object.class().expect("object had no class?"))
.context("object not of any base type?")?;
let ty = cache.identify_uobject(object);
let ty = UAnyType::from_uobject(object.as_uobject());
log::debug!("ty: {ty:?}");
match ty {
@ -161,13 +138,11 @@ pub mod sdk {
UAnyType::UClass(_) => {}
UAnyType::UField(_) => {}
UAnyType::UScriptStruct(_) => {}
UAnyType::UProperty(_) => {}
UAnyType::UEnum(obj) => {
let enm = Self::process_enum(obj)?;
log::info!("enum: {enm}");
}
UAnyType::UStruct(_) => {}
UAnyType::UFunction(_) => {}
}
}
@ -177,7 +152,7 @@ pub mod sdk {
fn process_enum(enm: UEnum) -> anyhow::Result<Enum> {
// get all the variants
let values = enm
.get_names()
.names()
.iter()
.enumerate()
// canonicalize the names into valid rust

View file

@ -6,7 +6,13 @@
//! that the contents might very well change under its feet (which they might).
#![allow(non_upper_case_globals)]
use bitflags::bitflags;
use std::{cell::UnsafeCell, marker::PhantomData, ptr::NonNull};
use std::{
cell::UnsafeCell,
fmt::{Debug, Display},
hash::Hash,
marker::PhantomData,
ptr::NonNull,
};
#[derive(Debug)]
#[repr(transparent)]
@ -178,14 +184,33 @@ define_utypes!(
UEnumProperty where UFieldTrait, UStructTrait, UPropertyTrait,UEnumPropertyTrait => "EnumProperty"
);
impl Hash for UObject {
fn hash<H: ~const std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl Display for UObject {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "UObject {{")?;
writeln!(f, "\tvtbl: {:?}", self.vtbl())?;
writeln!(f, "\tobject_flags{:?}", self.object_flags())?;
writeln!(f, "\tinternal_index{:?}", self.internal_index())?;
writeln!(f, "\tclass{:?}", self.class())?;
writeln!(f, "\tname{:?}", &self.get_name_or_default())?;
writeln!(f, "\touter{:?}", self.outer())?;
writeln!(f, "}}")
}
}
impl UObject {
#![allow(dead_code)]
const fn raw_ptr(&self) -> *const () {
const fn raw_ptr(&self) -> *const u8 {
unsafe { self.0.as_ref().get() as _ }
}
const fn raw_mut(&self) -> *mut () {
const fn raw_mut(&self) -> *mut u8 {
unsafe { self.0.as_ref().get() as _ }
}
@ -316,8 +341,61 @@ impl<'a> Iterator for ChildIter<'a> {
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum UAnyType {
UObject(UObject),
UClass(UClass),
UField(UField),
UScriptStruct(UScriptStruct),
UEnum(UEnum),
UStruct(UStruct),
}
impl UAnyType {
pub fn from_uobject(uobject: UObject) -> Self {
// remember to order this from most specialized to least.
// specifically: a UClass is also a UStruct, so check for UClass first,
// then for any other subtypes of UStruct, then for UStruct
if uobject.is_a(&UEnum::static_class()) {
Self::UEnum(unsafe { uobject.cast() })
} else if uobject.is_a(&UClass::static_class()) {
Self::UClass(unsafe { uobject.cast() })
} else if uobject.is_a(&UScriptStruct::static_class()) {
Self::UScriptStruct(unsafe { uobject.cast() })
} else if uobject.is_a(&UStruct::static_class()) {
Self::UStruct(unsafe { uobject.cast() })
} else if uobject.is_a(&UField::static_class()) {
Self::UField(unsafe { uobject.cast() })
} else {
Self::UObject(uobject)
}
}
}
impl AsUObject for UAnyType {
fn as_uobject(&self) -> self::UObject {
match self {
UAnyType::UObject(obj) => obj.as_uobject(),
UAnyType::UClass(obj) => obj.as_uobject(),
UAnyType::UField(obj) => obj.as_uobject(),
UAnyType::UScriptStruct(obj) => obj.as_uobject(),
UAnyType::UEnum(obj) => obj.as_uobject(),
UAnyType::UStruct(obj) => obj.as_uobject(),
}
}
fn from_raw(raw: *mut ()) -> Option<Self> {
UObject::from_raw(raw).map(|obj| Self::from_uobject(obj))
}
fn from_nonnull(raw: NonNull<UnsafeCell<()>>) -> Self {
Self::from_uobject(UObject::from_nonnull(raw))
}
}
use traits::*;
mod traits {
pub mod traits {
use std::cell::UnsafeCell;
use std::ptr::NonNull;
@ -338,17 +416,13 @@ mod traits {
static CLASS: OnceCell<super::UClass> = OnceCell::new();
*CLASS.get_or_init(|| {
super::UClass(
GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name())
.expect("static class not found!")
.inner
.cast(),
)
GOBJECTS
.read()
.unwrap()
.as_objects()
.unwrap()
.find_class(Self::static_class_name())
.expect("static class not found!")
})
}
}