From 99a3effc4c5ace928857091e61ec8045a24fa7d3 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 20 Apr 2023 20:48:54 +0200 Subject: [PATCH] handle possibility of missing static class (UMapProperty) --- src/v2_types/mod.rs | 92 +++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 24 deletions(-) diff --git a/src/v2_types/mod.rs b/src/v2_types/mod.rs index 8aa61d8..8495022 100644 --- a/src/v2_types/mod.rs +++ b/src/v2_types/mod.rs @@ -170,10 +170,34 @@ macro_rules! define_utypes { #[derive(Debug, Clone, Copy)] pub struct $ty(NonNull>); - impl $ty { - pub const fn static_class_name() -> &'static str { + impl traits::StaticClass for $ty { + fn static_class_name() -> &'static str { concat!("Class CoreUObject.", $name) } + + fn static_class() -> Option { + use crate::global_tables::objects::{FindClass, GOBJECTS}; + use once_cell::sync::OnceCell; + // this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types.. + static CLASS: OnceCell> = OnceCell::new(); + + *CLASS.get_or_init(|| { + let class = match GOBJECTS + .read() + .unwrap() + .as_objects() + .unwrap() + .find_class(Self::static_class_name()) { + Some(class) => {Some(class)}, + None => { + log::error!("static class \"{}\" not found!", Self::static_class_name()); + None + } + }; + log::info!("class for {} is {:?}", Self::static_class_name(), class); + class + }) + } } impl_asuobject!($ty); @@ -192,6 +216,30 @@ macro_rules! define_utypes { fn static_class_name() -> &'static str { concat!("Class CoreUObject.", $name) } + + fn static_class() -> Option { + use crate::global_tables::objects::{FindClass, GOBJECTS}; + use once_cell::sync::OnceCell; + // this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types.. + static CLASS: OnceCell> = OnceCell::new(); + + *CLASS.get_or_init(|| { + let class = match GOBJECTS + .read() + .unwrap() + .as_objects() + .unwrap() + .find_class(Self::static_class_name()) { + Some(class) => {Some(class)}, + None => { + log::error!("static class \"{}\" not found!", Self::static_class_name()); + None + } + }; + log::info!("class for {} is {:?}", Self::static_class_name(), class); + class + }) + } } impl_asuobject!($ty); @@ -453,15 +501,19 @@ impl UAnyType { // 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()) { + if uobject.is_a_maybe(&UClass::static_class()) { Self::UClass(unsafe { uobject.cast() }) - } else if uobject.is_a(&UScriptStruct::static_class()) { + } else if uobject.is_a_maybe(&UProperty::static_class()) { + Self::UProperty(unsafe { uobject.cast() }) + } else if uobject.is_a_maybe(&UFunction::static_class()) { + Self::UFunction(unsafe { uobject.cast() }) + } else if uobject.is_a_maybe(&UScriptStruct::static_class()) { Self::UScriptStruct(unsafe { uobject.cast() }) - } else if uobject.is_a(&UStruct::static_class()) { + } else if uobject.is_a_maybe(&UEnum::static_class()) { + Self::UEnum(unsafe { uobject.cast() }) + } else if uobject.is_a_maybe(&UStruct::static_class()) { Self::UStruct(unsafe { uobject.cast() }) - } else if uobject.is_a(&UField::static_class()) { + } else if uobject.is_a_maybe(&UField::static_class()) { Self::UField(unsafe { uobject.cast() }) } else { Self::UObject(uobject) @@ -497,30 +549,15 @@ pub mod traits { use anyhow::Context; use itertools::Itertools; - use once_cell::sync::OnceCell; use crate::fname::FName; - use crate::global_tables::objects::{FindClass, GOBJECTS}; use crate::tarray::{FString, TArray}; use super::{EObjectFlags, VTbl}; pub trait StaticClass { fn static_class_name() -> &'static str; - fn static_class() -> super::UClass { - // this is something that we always do in C/C++ but unfortinately requires a blanket impl Sync + Send on all UObject types.. - static CLASS: OnceCell = OnceCell::new(); - - *CLASS.get_or_init(|| { - GOBJECTS - .read() - .unwrap() - .as_objects() - .unwrap() - .find_class(Self::static_class_name()) - .expect("static class not found!") - }) - } + fn static_class() -> Option; } #[const_trait] @@ -601,6 +638,13 @@ pub mod traits { .map(|class| class.iter_super_classes().contains(other)) .unwrap_or(false) } + + fn is_a_maybe(&self, other: &Option) -> bool { + other + .as_ref() + .map(|class| self.is_a(class)) + .unwrap_or(false) + } } impl UObjectNonConst for T where T: UObjectTrait {}