v2 type def

This commit is contained in:
Janis 2023-04-20 00:41:48 +02:00
parent a2233bb3b4
commit 03c1c61d42
3 changed files with 438 additions and 0 deletions

1
rust-toolchain Normal file
View file

@ -0,0 +1 @@
nightly

View file

@ -1,6 +1,9 @@
#![feature(const_trait_impl, const_ptr_as_ref, const_nonnull_new)]
mod core_types;
pub mod global_tables;
pub mod types;
pub mod v2_types;
pub mod sdk {
use std::{

434
src/v2_types/mod.rs Normal file
View file

@ -0,0 +1,434 @@
//! This module is an attempt to define Unreal Types using just a pointer
//! because I thought that was proabably a lot safer and ergonomic than having a
//! bunch of nesting structures, and having to worry a lot more about aliasing
//! references. every type is also stored in an UnsafeCell which, if I
//! understand UnsafeCell and unsafe Rust correctly, should tell the compiler
//! 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, ptr::NonNull};
#[derive(Debug)]
#[repr(transparent)]
pub struct VTbl(NonNull<()>);
impl VTbl {}
bitflags! {
#[repr(C)]
pub struct EObjectFlags: u32 {
const RF_NoFlags = 0x00000000;
const RF_Public = 0x00000001;
const RF_Standalone = 0x00000002;
const RF_MarkAsNative = 0x00000004;
const RF_Transactional = 0x00000008;
const RF_ClassDefaultObject = 0x00000010;
const RF_ArchetypeObject = 0x00000020;
const RF_Transient = 0x00000040;
const RF_MarkAsRootSet = 0x00000080;
const RF_TagGarbageTemp = 0x00000100;
const RF_NeedInitialization = 0x00000200;
const RF_NeedLoad = 0x00000400;
const RF_KeepForCooker = 0x00000800;
const RF_NeedPostLoad = 0x00001000;
const RF_NeedPostLoadSubobjects = 0x00002000;
const RF_NewerVersionExists = 0x00004000;
const RF_BeginDestroyed = 0x00008000;
const RF_FinishDestroyed = 0x00010000;
const RF_BeingRegenerated = 0x00020000;
const RF_DefaultSubObject = 0x00040000;
const RF_WasLoaded = 0x00080000;
const RF_TextExportTransient = 0x00100000;
const RF_LoadCompleted = 0x00200000;
const RF_InheritableComponentTemplate = 0x00400000;
const RF_DuplicateTransient = 0x00800000;
const RF_StrongRefOnFrame = 0x01000000;
const RF_NonPIEDuplicateTransient = 0x02000000;
const RF_Dynamic = 0x04000000;
const RF_WillBeLoaded = 0x08000000;
const RF_HasExternalPackage = 0x10000000;
}
}
macro_rules! define_utypes {
($($ty:ident),+) => {
$(
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub struct $ty(NonNull<UnsafeCell<()>>);
impl_asuobject!($ty);
impl const traits::UObject for $ty {}
)+
};
($($ty:ident => $name:literal),+) => {
$(
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub struct $ty(NonNull<UnsafeCell<()>>);
impl $ty {
pub const fn static_class_name() -> &'static str {
concat!("Class CoreUObject.", $name)
}
}
impl_asuobject!($ty);
impl const traits::UObjectTrait for $ty {}
)+
};
}
macro_rules! impl_const_trait_for {
($trt:ty: $($ty:ty),+) => {
$(
impl const $trt for $ty {}
)+
};
}
macro_rules! impl_asuobject {
($($ty:ty),+) => {
$(
impl $ty {
pub const fn from_raw(raw: *mut ()) -> Option<Self> {
match NonNull::new(raw) {
Some(ptr) => Some(Self(ptr.cast())),
None => None,
}
}
pub const fn from_nonnull(raw: NonNull<UnsafeCell<()>>) -> Self {
Self(raw)
}
}
impl const traits::AsUObject for $ty {
fn as_uobject(&self) -> self::UObject {
self::UObject(self.0)
}
}
)+
};
}
define_utypes!(
UObject => "Object",
UField => "Field",
UEnum => "Enum",
UStruct => "Struct",
UScriptStruct => "ScriptStruct",
UClass => "Class",
UProperty => "Property",
UFunction => "Function",
UNumericProperty => "NumericProperty",
UByteProperty => "ByteProperty",
UUInt16Property => "UInt16Property",
UUInt32Property => "UInt32Property",
UUInt64Property => "UInt64Property",
UInt8Property => "Int8Property",
UInt16Property => "Int16Property",
UIntProperty => "IntProperty", // i32
UInt64Property => "Int64Property",
UFloatProperty => "FloatProperty",
UDoubleProperty => "DoubleProperty",
UBoolProperty => "BoolProperty",
UObjectPropertyBase => "ObjectPropertyBase",
UObjectProperty => "ObjectProperty",
UClassProperty => "ClassProperty",
UInterfaceProperty => "InterfaceProperty",
UWeakObjectProperty => "WeakObjectProperty",
ULazyObjectProperty => "LazyObjectProperty",
UAssetObjectProperty => "AssetObjectProperty",
UAssetClassProperty => "AssetClassProperty",
USoftObjectProperty => "SoftObjectProperty",
UNameProperty => "NameProperty",
UStructProperty => "StructProperty",
UStrProperty => "StrProperty",
UTextProperty => "TextProperty",
UArrayProperty => "ArrayProperty",
UMapProperty => "MapProperty",
UDelegateProperty => "DelegateProperty",
UMulticastDelegateProperty => "MulticastDelegateProperty",
UEnumProperty => "EnumProperty"
);
// impl_const_trait_for!(
// traits::UFieldTrait: UField,
// UEnum,
// UStruct,
// UClass,
// UProperty
// );
// impl_const_trait_for!(traits::UStructTrait: UStruct, UClass);
// impl_const_trait_for!(traits::UEnumTrait: UEnum);
// impl_const_trait_for!(traits::UPropertyTrait: UProperty);
impl UObject {
#![allow(dead_code)]
const fn raw_ptr(&self) -> *const () {
unsafe { self.0.as_ref().get() as _ }
}
const fn raw_mut(&self) -> *mut () {
unsafe { self.0.as_ref().get() as _ }
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum ECppForm {
Regular,
Namespaced,
EnumClass,
}
impl UEnum {
pub fn cpp_form(&self) -> Option<ECppForm> {
match *traits::UEnumTrait::cpp_form_raw(self) {
0 => Some(ECppForm::Regular),
1 => Some(ECppForm::Namespaced),
2 => Some(ECppForm::EnumClass),
_ => None,
}
}
}
mod traits {
use std::ptr::NonNull;
use crate::core_types::{FName, FString, TArray};
use super::{EObjectFlags, VTbl};
#[const_trait]
pub trait AsUObject {
fn as_uobject(&self) -> super::UObject;
}
#[const_trait]
pub trait UObjectTrait: ~const AsUObject {
fn vtbl(&self) -> &VTbl {
unsafe { &*self.as_uobject().raw_ptr().offset(0).cast() }
}
fn object_flags(&self) -> &EObjectFlags {
unsafe { &*self.as_uobject().raw_ptr().offset(8).cast() }
}
fn internal_index(&self) -> &u32 {
unsafe { &*self.as_uobject().raw_ptr().offset(12).cast() }
}
fn class(&self) -> &Option<super::UClass> {
unsafe { &*self.as_uobject().raw_ptr().offset(16).cast() }
}
fn name(&self) -> &FName {
unsafe { &*self.as_uobject().raw_ptr().offset(24).cast() }
}
fn outer(&self) -> &Option<super::UObject> {
unsafe { &*self.as_uobject().raw_ptr().offset(32).cast() }
}
}
#[const_trait]
pub trait UFieldTrait: ~const AsUObject {
fn next(&self) -> &Option<super::UField> {
unsafe { &*self.as_uobject().raw_ptr().offset(40).cast() }
}
}
#[const_trait]
pub trait UEnumTrait: ~const AsUObject {
fn cpp_type(&self) -> &FString {
unsafe { &*self.as_uobject().raw_ptr().offset(48).cast() }
}
fn names(&self) -> &TArray<FName> {
unsafe { &*self.as_uobject().raw_ptr().offset(64).cast() }
}
fn cpp_form_raw(&self) -> &u32 {
unsafe { &*self.as_uobject().raw_ptr().offset(80).cast() }
}
}
impl<T> const UFieldTrait for T where T: ~const UEnumTrait {}
#[const_trait]
pub trait UStructTrait: ~const UFieldTrait {
fn super_field(&self) -> &Option<super::UStruct> {
unsafe { &*self.as_uobject().raw_ptr().offset(48).cast() }
}
fn children(&self) -> &Option<super::UField> {
unsafe { &*self.as_uobject().raw_ptr().offset(56).cast() }
}
fn property_size(&self) -> &u32 {
unsafe { &*self.as_uobject().raw_ptr().offset(64).cast() }
}
fn min_alignment(&self) -> &u32 {
unsafe { &*self.as_uobject().raw_ptr().offset(68).cast() }
}
}
#[const_trait]
pub trait UScriptStructTrait: ~const UStructTrait {}
#[const_trait]
pub trait UClassTrait: ~const UStructTrait {}
#[const_trait]
pub trait UFunctionTrait: ~const UStructTrait {
fn function_flags(&self) -> &u32 {
unsafe { &*self.as_uobject().raw_ptr().offset(144).cast() }
}
fn rep_offset(&self) -> &u16 {
unsafe { &*self.as_uobject().raw_ptr().offset(148).cast() }
}
fn num_params(&self) -> &u8 {
unsafe { &*self.as_uobject().raw_ptr().offset(150).cast() }
}
fn params_size(&self) -> &u16 {
unsafe { &*self.as_uobject().raw_ptr().offset(152).cast() }
}
fn return_value_offset(&self) -> &u16 {
unsafe { &*self.as_uobject().raw_ptr().offset(154).cast() }
}
fn rpc_id(&self) -> &u16 {
unsafe { &*self.as_uobject().raw_ptr().offset(156).cast() }
}
fn rpc_response_id(&self) -> &u16 {
unsafe { &*self.as_uobject().raw_ptr().offset(158).cast() }
}
fn first_property_to_init(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(160).cast() }
}
fn func(&self) -> &Option<NonNull<()>> {
unsafe { &*self.as_uobject().raw_ptr().offset(168).cast() }
}
}
#[const_trait]
pub trait UPropertyTrait: ~const UFieldTrait {
fn array_dim(&self) -> &i32 {
unsafe { &*self.as_uobject().raw_ptr().offset(48).cast() }
}
fn element_size(&self) -> &i32 {
unsafe { &*self.as_uobject().raw_ptr().offset(52).cast() }
}
fn property_flags(&self) -> &u64 {
unsafe { &*self.as_uobject().raw_ptr().offset(56).cast() }
}
fn rep_index(&self) -> &i16 {
unsafe { &*self.as_uobject().raw_ptr().offset(64).cast() }
}
fn rep_notify_function(&self) -> &FName {
unsafe { &*self.as_uobject().raw_ptr().offset(68).cast() }
}
fn offset(&self) -> &i32 {
unsafe { &*self.as_uobject().raw_ptr().offset(76).cast() }
}
fn property_link_next(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(80).cast() }
}
fn next_ref(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(88).cast() }
}
fn destructor_link_next(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(96).cast() }
}
fn post_construct_link_next(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(104).cast() }
}
}
#[const_trait]
pub trait UBytePropertyTrait: ~const UPropertyTrait {
fn uenum(&self) -> &Option<super::UEnum> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
}
#[const_trait]
pub trait UBoolPropertyTrait: ~const UPropertyTrait {
fn field_size(&self) -> &u8 {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
fn byte_offset(&self) -> &u8 {
unsafe { &*self.as_uobject().raw_ptr().offset(113).cast() }
}
fn byte_mask(&self) -> &u8 {
unsafe { &*self.as_uobject().raw_ptr().offset(114).cast() }
}
fn field_mask(&self) -> &u8 {
unsafe { &*self.as_uobject().raw_ptr().offset(115).cast() }
}
}
#[const_trait]
pub trait UObjectPropertyBaseTrait: ~const UPropertyTrait {
fn property_class(&self) -> &Option<super::UClass> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
}
#[const_trait]
pub trait UInterfacePropertyTrait: ~const UPropertyTrait {
fn interface_class(&self) -> &Option<super::UClass> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
}
#[const_trait]
pub trait UStructPropertyTrait: ~const UPropertyTrait {
fn ustruct(&self) -> &Option<super::UStruct> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
}
#[const_trait]
pub trait UArrayPropertyTrait: ~const UPropertyTrait {
fn inner(&self) -> &Option<super::UClass> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
}
#[const_trait]
pub trait UMapPropertyTrait: ~const UPropertyTrait {
fn key_prop(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
fn value_prop(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(120).cast() }
}
}
#[const_trait]
pub trait UClassPropertyTrait: ~const UObjectPropertyBaseTrait {
fn meta_class(&self) -> &Option<super::UClass> {
unsafe { &*self.as_uobject().raw_ptr().offset(120).cast() }
}
}
#[const_trait]
pub trait UAssetClassPropertyTrait: ~const UObjectPropertyBaseTrait {
fn meta_class(&self) -> &Option<super::UClass> {
unsafe { &*self.as_uobject().raw_ptr().offset(120).cast() }
}
}
#[const_trait]
pub trait UDelegatePropertyTrait: ~const UPropertyTrait {
fn signature_function(&self) -> &Option<super::UFunction> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
}
#[const_trait]
pub trait UEnumPropertyTrait: ~const UPropertyTrait {
fn underlying_type(&self) -> &Option<super::UProperty> {
unsafe { &*self.as_uobject().raw_ptr().offset(112).cast() }
}
fn uenum(&self) -> &Option<super::UEnum> {
unsafe { &*self.as_uobject().raw_ptr().offset(120).cast() }
}
}
}