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

View file

@ -1,10 +1,10 @@
#![feature(const_trait_impl, const_ptr_as_ref, const_nonnull_new)] #![feature(const_trait_impl, const_ptr_as_ref, const_nonnull_new)]
mod core_types; // mod core_types;
pub mod fname; pub mod fname;
pub mod global_tables; pub mod global_tables;
pub mod tarray; pub mod tarray;
pub mod types; // pub mod types;
pub mod v2_types; pub mod v2_types;
pub mod sdk { pub mod sdk {
@ -19,17 +19,12 @@ pub mod sdk {
use crate::{ use crate::{
global_tables::objects::{FindClass, GOBJECTS}, 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 { struct ClassCache {
classes: Mutex<HashMap<String, UClass>>, 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<()> { pub fn cache_class(&mut self, class: UClass) -> anyhow::Result<()> {
let name = class.get_full_name()?; let name = class.get_full_name()?;
self.classes.lock().unwrap().insert(name, class); self.classes.lock().unwrap().insert(name, class);
@ -109,7 +86,7 @@ pub mod sdk {
// ensure item contains object // ensure item contains object
.filter_map(|item| item.object()) .filter_map(|item| item.object())
// get package object // get package object
.filter_map(|obj| obj.outermost().map(|pkg| (pkg, obj))) .map(|obj| (obj.package_object(), obj))
.fold( .fold(
HashMap::<UObject, Vec<UObject>>::new(), HashMap::<UObject, Vec<UObject>>::new(),
|mut acc, (pkg, obj)| { |mut acc, (pkg, obj)| {
@ -153,7 +130,7 @@ pub mod sdk {
.cache_class(object.class().expect("object had no class?")) .cache_class(object.class().expect("object had no class?"))
.context("object not of any base type?")?; .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:?}"); log::debug!("ty: {ty:?}");
match ty { match ty {
@ -161,13 +138,11 @@ pub mod sdk {
UAnyType::UClass(_) => {} UAnyType::UClass(_) => {}
UAnyType::UField(_) => {} UAnyType::UField(_) => {}
UAnyType::UScriptStruct(_) => {} UAnyType::UScriptStruct(_) => {}
UAnyType::UProperty(_) => {}
UAnyType::UEnum(obj) => { UAnyType::UEnum(obj) => {
let enm = Self::process_enum(obj)?; let enm = Self::process_enum(obj)?;
log::info!("enum: {enm}"); log::info!("enum: {enm}");
} }
UAnyType::UStruct(_) => {} UAnyType::UStruct(_) => {}
UAnyType::UFunction(_) => {}
} }
} }
@ -177,7 +152,7 @@ pub mod sdk {
fn process_enum(enm: UEnum) -> anyhow::Result<Enum> { fn process_enum(enm: UEnum) -> anyhow::Result<Enum> {
// get all the variants // get all the variants
let values = enm let values = enm
.get_names() .names()
.iter() .iter()
.enumerate() .enumerate()
// canonicalize the names into valid rust // 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). //! that the contents might very well change under its feet (which they might).
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
use bitflags::bitflags; 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)] #[derive(Debug)]
#[repr(transparent)] #[repr(transparent)]
@ -178,14 +184,33 @@ define_utypes!(
UEnumProperty where UFieldTrait, UStructTrait, UPropertyTrait,UEnumPropertyTrait => "EnumProperty" 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 { impl UObject {
#![allow(dead_code)] #![allow(dead_code)]
const fn raw_ptr(&self) -> *const () { const fn raw_ptr(&self) -> *const u8 {
unsafe { self.0.as_ref().get() as _ } 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 _ } 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::*; use traits::*;
mod traits { pub mod traits {
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::ptr::NonNull; use std::ptr::NonNull;
@ -338,7 +416,6 @@ mod traits {
static CLASS: OnceCell<super::UClass> = OnceCell::new(); static CLASS: OnceCell<super::UClass> = OnceCell::new();
*CLASS.get_or_init(|| { *CLASS.get_or_init(|| {
super::UClass(
GOBJECTS GOBJECTS
.read() .read()
.unwrap() .unwrap()
@ -346,9 +423,6 @@ mod traits {
.unwrap() .unwrap()
.find_class(Self::static_class_name()) .find_class(Self::static_class_name())
.expect("static class not found!") .expect("static class not found!")
.inner
.cast(),
)
}) })
} }
} }