From f8f183c420c1ac0a60e7101a5806c0458b40cf33 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 20 Apr 2023 03:35:31 +0200 Subject: [PATCH] using pointer types now for every coreuobject type --- src/global_tables/names.rs | 2 +- src/global_tables/objects.rs | 34 ++++++++---- src/lib.rs | 43 +++------------ src/v2_types/mod.rs | 104 ++++++++++++++++++++++++++++++----- 4 files changed, 121 insertions(+), 62 deletions(-) diff --git a/src/global_tables/names.rs b/src/global_tables/names.rs index 15d21e9..8fbb63b 100644 --- a/src/global_tables/names.rs +++ b/src/global_tables/names.rs @@ -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 = RwLock::new(GNames::new()); diff --git a/src/global_tables/objects.rs b/src/global_tables/objects.rs index bc96438..4ca4482 100644 --- a/src/global_tables/objects.rs +++ b/src/global_tables/objects.rs @@ -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 = RwLock::new(GObjects::new()); @@ -10,7 +13,7 @@ lazy_static::lazy_static! { #[derive(Debug, Default)] pub struct GObjects { - objects: Option>, + objects: Option>>, } impl GObjects { @@ -19,11 +22,12 @@ impl GObjects { } pub fn set_objects(&mut self, objects: NonNull) { - 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>, + object: Option, 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::maybe_new(self.object) + pub fn object(&self) -> Option { + self.object } } @@ -233,22 +237,28 @@ pub mod par_iter { } pub trait FindClass { - fn find_class(&self, class_name: S) -> Option + fn find_class(&self, class_name: S) -> Option where S: Into; } impl FindClass for ObjectArray { - fn find_class(&self, class_name: S) -> Option + fn find_class(&self, class_name: S) -> Option where S: Into, { + 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() } } diff --git a/src/lib.rs b/src/lib.rs index e9d4033..34c057f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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>, } @@ -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::>::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 { // get all the variants let values = enm - .get_names() + .names() .iter() .enumerate() // canonicalize the names into valid rust diff --git a/src/v2_types/mod.rs b/src/v2_types/mod.rs index fc2a119..a41b5d8 100644 --- a/src/v2_types/mod.rs +++ b/src/v2_types/mod.rs @@ -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(&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 { + UObject::from_raw(raw).map(|obj| Self::from_uobject(obj)) + } + + fn from_nonnull(raw: NonNull>) -> 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 = 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!") }) } }